#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qRegisterMetaType<qintptr>("qintptr");//注册自定义数据类型

    updateSerialPortList();//初始化可用端口列表

    iniSerialPort();//初始串口信息

    m_statueLab0.setText(tr("串口通信"));//初始化状态栏信息
    m_statueLab1.setText(tr("状态:已关闭"));
    m_statueLab2.setText(tr("串口:")+ui->combSerialPort->currentText());
    m_statueLab3.setText(tr("发送设置:Ascll"));
    m_statueLab4txt.setText(tr("发送: "));
    m_statueLab4.setText("0");
    m_statueLab5txt.setText(tr("接收: "));
    m_statueLab5.setText("0");
    ui->statusbar->addWidget(&m_statueLab0,1);
    ui->statusbar->addWidget(&m_statueLab1,1);
    ui->statusbar->addWidget(&m_statueLab2,1);
    ui->statusbar->addWidget(&m_statueLab3,1);
    ui->statusbar->addWidget(&m_statueLab4txt);
    ui->statusbar->addWidget(&m_statueLab4,1);
    ui->statusbar->addWidget(&m_statueLab5txt);
    ui->statusbar->addWidget(&m_statueLab5,1);

    ui->stackedWidget->setCurrentWidget(ui->pagSerial);
    ui->actSerialPortWindow->setChecked(true);//默认为串口调试窗口

    m_originalAcceptString = "";//初始接收的原生字符串为空
    m_recByteArray.clear();//接受字符串置空

    m_isConnect = false;//串口连接状态默认关闭
    m_isAcceptRec = true;//默认允许接收

    ui->btnSend->setEnabled(false);//发送按钮默认不可用
    ui->btnClearAcceptText->setEnabled(false);
    ui->btnClearSendText->setEnabled(false);
    ui->btnSendFile->setEnabled(false);
    ui->btnSerialLogSave->setEnabled(false);
    ui->btnSerialSave->setEnabled(false);
    ui->btnPauseAccept->setEnabled(false);
    ui->cheRecFile->hide();//隐藏串口调试接收文件的复选框


    ui->btnPauseAccept->setIcon(QIcon(":/img/getConnect.png"));//为暂停接收按钮设置图片

    ui->btnRefreshSerialPort->setDefaultAction(ui->actUpdate);//绑定默认行为
    ui->btnCustomBandRate->setDefaultAction(ui->actCustomBundRate);

    m_reSendInterval = ui->spinBoxSendTime->value();//默认重复发送时间间隔为1000ms
    m_reSendTimer.setInterval(m_reSendInterval);//设置初始化发送时间间隔

    m_sendFileSignalSize = 128;//设置默认文件发送单次长度为128

    //    setSetingVisiable(false);//串口界面部分设置禁用

    ui->groupSerialSendFile->hide();//禁用串口发送文件功能

    //初始化接收发送计数
    m_recCountSerial = 0;
    m_sendCountSerial = 0;

    connect(&m_reSendTimer,SIGNAL(timeout()),this,SLOT(on_timer_out()));//关联定时器和其响应函数
    connect(ui->toolBar,SIGNAL(actionTriggered(QAction*)),this,SLOT(on_Window_changed(QAction*)));
    //    connect(&m_serialPort,SIGNAL(readyRead()),this,SLOT(on_serialPort_readyRead()));//连接接受信息槽函数,详见2第40行



    //以下代码用于实现网络调试
    //以下代码用于实现网络调试
    //以下代码用于实现网络调试
    iniNetWindow();//初始化

    m_tcpServer = new mytcpserver(this);//实例化成员变量
    m_tcpSocket = new QTcpSocket(this);
    m_udpSocket = new QUdpSocket(this);

    ui->btnUpdateNet->setDefaultAction(ui->actUpdateNet);//连接默认action

    m_isConnectNet = false;//默认没有连接
    m_isAcceptRecNet = true;//默认网络调试允许接收

    m_waitForConnectTime = 2000;//默认作为客户端等待连接的超时时间为2s

    m_timerNet = new QTimer(this);//实例化网络调试连接状态对象的检查定时器
    m_timerNet->setInterval(2000);//检测socket连接状态,默认间隔为2s

    m_originalAcceptStringNet = "";//初始网络接收的原生字符串为空

    m_timerReSendNetInterval = ui->spinBoxSendIntervalNet->value();//初始化络重复发送的定时器测间隔
    m_timerReSendNet = new QTimer(this);//实例化网络重复发送的定时器
    m_timerReSendNet->setInterval(m_timerReSendNetInterval);//初始化定时器检测间隔

    ui->btnSendNet->setEnabled(false);//设置部分按钮默认不可互动
    ui->btnClearSendNet->setEnabled(false);
    ui->btnClearRecNet->setEnabled(false);
    ui->btnSaveLogNet->setEnabled(false);
    ui->btnSaveDateNet->setEnabled(false);

    //初始化接收发送计数
    m_recCountNet = 0;
    m_sendCountNet = 0;

    //初始化udp设置控件可互动
    ui->groupUdpCast->setEnabled(false);

    //设置新建tcp客户端窗口按钮不可互动
    ui->btnNewTcpServiceNet->setEnabled(false);
    ui->btnNewTcpServiceNet->hide();

    m_isBindNet = false;//初始化udp通信未绑定

    m_isJoinMultiNet = false;//初始化udp通信未加入多播组

    ui->editTargetHostNet->setText(getIPv4Address().at(0).toString());//设置udp目标地址默认为本机地址

    m_udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);//初始化udp组播的数据报生存期为1


    connect(m_tcpServer,SIGNAL(newDescriptoe(qintptr)),this,SLOT(on_socket_connected(qintptr)));//当启动tcp服务器监听后有新的连接则触发此槽函数
    connect(m_tcpSocket,SIGNAL(connected()),this,SLOT(on_asTcpClient_Connecte()));//连接socket连接成功时的响应函数
    connect(m_tcpSocket,SIGNAL(disconnected()),this,SLOT(on_socket_disconnected()));//断开socket连接时的响应函数
    connect(m_tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(on_socket_stateChanged()));//当socket状态改变时调用此函数
    connect(m_timerNet,SIGNAL(timeout()),this,SLOT(on_timerNet_timeout()));//连接响应保活计时器的槽函数
    connect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(on_tcpSocket_readyRead()));//连接tcpsocket读写槽函数
    connect(m_timerReSendNet,SIGNAL(timeout()),this,SLOT(on_timerReSend_timeout()));//连接响应网络调试重复发送的槽函数
    connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(on_udpSocket_readyRead()));//连接udp读写槽函数

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_btnConnect_clicked()
{
    if(m_isConnect == true){//串口已经连接,则执行关闭操作
        if(setConnectStatue(false) == true){//如果断开连接成功则设置文件发送按钮不可互动
            ui->btnSendFile->setEnabled(false);
            m_statueLab1.setText(tr("状态:已关闭"));
        }
    }else if(m_isConnect == false){//串口已经关闭,则执行打开操作
        if(setConnectStatue(true)  == true){//如果连接打开成功并且满足条件则设置文件发送按钮可以互动
            m_statueLab1.setText(tr("状态:已打开"));
            if(ui->editFilePath->text().isEmpty() || ui->editFilePath->text().isNull() || m_isConnect == false){
                ui->btnSendFile->setEnabled(false);//文件发送按钮不可互动
            }else{
                ui->btnSendFile->setEnabled(true);//文件发送按钮可以互动
            }
        }
    }
}

void MainWindow::iniSerialPort()
{
    //初始设置
    if(serialPortList.count() > 0){
        m_serialPort.setPortName(ui->combSerialPort->currentText());//初始化串口
    }
    m_serialPort.setBaudRate(ui->combBaudRate->currentText().toInt());//初始化波特率

    //初始化校验位

    if(ui->combParity->currentIndex() == 0){
        m_serialPort.setParity(QSerialPort::NoParity);//无校验
    }else if(ui->combParity->currentIndex() == 1){
        m_serialPort.setParity(QSerialPort::OddParity);//奇校验
    }else if(ui->combParity->currentIndex() == 2){
        m_serialPort.setParity(QSerialPort::EvenParity);//偶校验
    }else if(ui->combParity->currentIndex() == 3){
        m_serialPort.setParity(QSerialPort::MarkParity);//1校验
    }else if(ui->combParity->currentIndex() == 4){
        m_serialPort.setParity(QSerialPort::SpaceParity);//0校验
    }

    //初始化数据位
    if(ui->combDataBits->currentIndex() == 0){
        m_serialPort.setDataBits(QSerialPort::Data8);//数据位8
    }else if(ui->combDataBits->currentIndex() == 1){
        m_serialPort.setDataBits(QSerialPort::Data7);//数据位7
    }else if(ui->combDataBits->currentIndex() == 2){
        m_serialPort.setDataBits(QSerialPort::Data6);//数据位6
    }
    else if(ui->combDataBits->currentIndex() == 3){
        m_serialPort.setDataBits(QSerialPort::Data5);//数据位5
    }

    //初始化停止位
    if(ui->combStopBit->currentIndex() == 0){
        m_serialPort.setStopBits(QSerialPort::OneStop);//停止位1
    }else if(ui->combStopBit->currentIndex() == 1){
        m_serialPort.setStopBits(QSerialPort::OneAndHalfStop);//停止位1.5
    }else if(ui->combStopBit->currentIndex() == 2){
        m_serialPort.setStopBits(QSerialPort::TwoStop);//停止位2
    }

    //初始化流控
    if(ui->combFlowControl->currentIndex() == 0){
        m_serialPort.setFlowControl(QSerialPort::NoFlowControl);//无流控
    }else if(ui->combFlowControl->currentIndex() == 1){
        m_serialPort.setFlowControl(QSerialPort::SoftwareControl);//软件流控
    }else if(ui->combFlowControl->currentIndex() == 2){
        m_serialPort.setFlowControl(QSerialPort::HardwareControl);//硬件流控
    }
}

bool MainWindow::setConnectStatue(bool statue)
{
    //同步串口信息
    if(m_serialPort.isOpen() == true){//已经打开
        m_isConnect = true;
        ui->btnConnect->setText(tr("已打开"));
        ui->btnConnect->setIcon(QIcon(":/img/getConnect.png"));
    }else if(m_serialPort.isOpen() == false){//已经关闭
        m_isConnect = false;
        ui->btnConnect->setText(tr("已关闭"));
        ui->btnConnect->setIcon(QIcon(":/img/loseConnect.png"));
    }


    //执行打开操作
    if(statue == true && m_isConnect == true){
        QMessageBox::information(0,tr("提示"),tr("串口已经连接,请勿重复操作."));
        return true;
    }
    if(statue == false && m_isConnect == false){
        return true;
    }

    if(statue  == true && m_isConnect == false){
        if(m_serialPort.open(QSerialPort::ReadWrite) == false){//打开失败
            QMessageBox::warning(0,tr("警告"),tr("串口连接失败,此串口可能已经被占用."));
            return false;
        }else{//打开成功
            m_isConnect = true;
            ui->btnConnect->setText(tr("已打开"));
            ui->btnConnect->setIcon(QIcon(":/img/getConnect.png"));
            if(!(ui->textMainSend->toPlainText().isEmpty() || ui->textMainSend->toPlainText().isNull())){//连接成功并且发送框有内容时发送按钮可以互动
                ui->btnSend->setEnabled(true);
            }

            if(m_isAcceptRec == true){//在以上条件下,并且允许接收信息才连接响应函数
                connect(&m_serialPort,SIGNAL(readyRead()),this,SLOT(on_serialPort_readyRead()));//连接接受信息槽函数
            }
            ui->btnPauseAccept->setEnabled(true);//设置暂停接收按钮可用

            //打开成功后设置参数不能更改
            ui->combBaudRate->setEnabled(false);
            ui->combDataBits->setEnabled(false);
            ui->combParity->setEnabled(false);
            ui->combFlowControl->setEnabled(false);
            ui->combSerialPort->setEnabled(false);
            ui->combStopBit->setEnabled(false);
            ui->actUpdate->setEnabled(false);
            ui->actCustomBundRate->setEnabled(false);

            return true;
        }
    }

    else if(statue == false && m_isConnect == true){
        m_serialPort.close();//关闭当前连接
        m_isConnect = false;
        ui->btnConnect->setText(tr("已关闭"));
        ui->btnConnect->setIcon(QIcon(":/img/loseConnect.png"));
        ui->btnSend->setEnabled(false);//关闭连接后发送按钮不可用

        disconnect(&m_serialPort,SIGNAL(readyRead()),this,SLOT(on_serialPort_readyRead()));//断开接受信息槽函数
        ui->btnPauseAccept->setEnabled(false);//设置暂停接收按钮不可用

        //关闭成功后设置参数可以更改
        ui->combBaudRate->setEnabled(true);
        ui->combDataBits->setEnabled(true);
        ui->combParity->setEnabled(true);
        ui->combFlowControl->setEnabled(true);
        ui->combSerialPort->setEnabled(true);
        ui->combStopBit->setEnabled(true);
        ui->actUpdate->setEnabled(true);
        ui->actCustomBundRate->setEnabled(true);

        return true;
    }

    //以上代码已经涵盖所有可能情况,如果一下代码实现则发生错误
    QMessageBox::warning(0,tr("警告"),tr("发生未知错误!"));
    return false;
}

int MainWindow::updateSerialPortList()
{
    serialPortList = QSerialPortInfo::availablePorts();//获取可用串口号
    int portCount = serialPortList.count();//记录可用端口数量
    ui->combSerialPort->clear();//清空原有串口号
    for(int i = 0;i < portCount; ++i){//遍历列表,依次在串口comb中添加可用串口号
        ui->combSerialPort->addItem(serialPortList.at(i).portName());
    }

    if(portCount > 0){//如果至少有一个可用端口就把当前索引设置为0
        ui->combSerialPort->setCurrentIndex(0);
    }else{//没有可用端口
        ui->combSerialPort->addItem(tr("无"));
    }
    return portCount;
}

int MainWindow::getThreadIndexNet()
{
    int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
    for(int i = m_tcpWidgetList.count() - 1;i >= 0;--i){
        if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
            index = i;
            break;
        }
    }
    return index;
}

void MainWindow::on_combSerialPort_currentTextChanged(const QString &arg1)
{
    m_serialPort.setPortName(arg1);
    m_statueLab2.setText(tr("串口:")+ui->combSerialPort->currentText());
}


void MainWindow::on_combBaudRate_currentTextChanged(const QString &arg1)
{
    m_serialPort.setBaudRate(arg1.toInt());

}

void MainWindow::on_combDataBits_currentIndexChanged(int index)
{
    if(index == 0){
        m_serialPort.setDataBits(QSerialPort::Data8);//数据位8
    }else if(index == 1){
        m_serialPort.setDataBits(QSerialPort::Data7);//数据位7
    }else if(index == 2){
        m_serialPort.setDataBits(QSerialPort::Data6);//数据位6
    }
    else if(index == 3){
        m_serialPort.setDataBits(QSerialPort::Data5);//数据位5
    }
}


void MainWindow::on_combParity_currentIndexChanged(int index)
{
    Q_UNUSED(index);
    if(ui->combParity->currentIndex() == 0){
        m_serialPort.setParity(QSerialPort::NoParity);//无校验
    }else if(ui->combParity->currentIndex() == 1){
        m_serialPort.setParity(QSerialPort::OddParity);//奇校验
    }else if(ui->combParity->currentIndex() == 2){
        m_serialPort.setParity(QSerialPort::EvenParity);//偶校验
    }else if(ui->combParity->currentIndex() == 3){
        m_serialPort.setParity(QSerialPort::MarkParity);//1校验
    }else if(ui->combParity->currentIndex() == 4){
        m_serialPort.setParity(QSerialPort::SpaceParity);//0校验
    }
}


void MainWindow::on_combStopBit_currentIndexChanged(int index)
{
    Q_UNUSED(index);
    if(ui->combStopBit->currentIndex() == 0){
        m_serialPort.setStopBits(QSerialPort::OneStop);//停止位1
    }else if(ui->combStopBit->currentIndex() == 1){
        m_serialPort.setStopBits(QSerialPort::OneAndHalfStop);//停止位1.5
    }else if(ui->combStopBit->currentIndex() == 2){
        m_serialPort.setStopBits(QSerialPort::TwoStop);//停止位2
    }
}


void MainWindow::on_actUpdate_triggered()
{
    updateSerialPortList();
    iniSerialPort();
}


void MainWindow::on_btnSend_clicked()
{
    if(m_serialPort.isOpen() == false){//错误检查
        QMessageBox::warning(0,tr("警告"),tr("程序出错!连接未打开."));
    }

    //定时器启动关闭,开始重复发送
    if(ui->cheReSend->isChecked() == true){//如果选中重复发送
        if(m_reSendTimer.isActive() == false){//如果定时器停止
            ui->btnSend->setText(tr("已打开"));
            ui->btnSend->setIcon(QIcon(":/img/getConnect.png"));
            m_reSendTimer.start();//启动定时器
            ui->textMainAccept->append(tr("重复发送开始:"));
        }else if(m_reSendTimer.isActive() == true){
            ui->btnSend->setText(tr("已关闭"));
            ui->btnSend->setIcon(QIcon(":/img/loseConnect.png"));
            m_reSendTimer.stop();//关闭定时器
            ui->textMainAccept->append(tr("重复发送结束."));
        }
        return;
    }

    //以下代码当重复发送框没被选中时实现,即发送模式为单次发送
    QString sendStr = ui->textMainSend->toPlainText();
    QString resultStr;

    if(ui->radioSendHEX->isChecked() == true){//如果勾选发送为16进制
        static QRegularExpression re("\\s");
        sendStr = sendStr.simplified().remove(re);

        if(sendStr.size()%2 != 0){//自动补全
            sendStr.insert(0,'0');
        }

        //        QString hexStr;
        //        bool ok;
        //        for(int i = 0;i < sendStr.size()/2;++i){
        //            hexStr += sendStr.mid(2*i,2).toInt(&ok,16);//切割字符串
        //        }

        resultStr = sendStr;//获得hex格式的内容

    }else{
        resultStr = sendStr;//获得ascll格式的内容
    }

    //    resultStr = sendStr;
    //    qDebug()<<resultStr;

    m_serialPort.write(resultStr.toUtf8());//发送内容数据
    m_sendCountSerial += resultStr.size();//发送计数
    m_statueLab4.setText(QString::asprintf("%d",m_sendCountSerial));

    //以下代码用于UI显示加工内容
    if(ui->cheAccoptShowSend->isChecked() == true){//如果勾选显示发送框
        ui->btnSerialLogSave->setEnabled(true);

        //        if(ui->radioSendHEX->isChecked() == true){//如果勾选以16进制发送
        //            resultStr = resultStr.simplified().remove("\\s");
        //            if(resultStr.size()%2 != 0){//自动补全
        //                resultStr.insert(0,'0');
        //            }
        //        }

        if(ui->radioSendAscll->isChecked() == true){//以ascll编码形式发送
            resultStr.prepend(tr("[Ascll 发送]:"));
        }else if(ui->radioSendHEX->isChecked() == true){//以hex编码形式发送
            resultStr.prepend(tr("[Hex 发送]:"));
        }

        if(ui->cheAcceptShowTime->isChecked() == true){//如果勾选显示时间
            resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
        }
        if(ui->cheAcceptAutoLine->isChecked() == true){//如果勾选自动换行
            ui->textMainAccept->append(resultStr);
            return;
        }
        ui->textMainAccept->insertPlainText(resultStr);
    }
}

void MainWindow:: on_serialPort_readyRead()
{
    //如果勾选接收文件框则接收文件
    if(ui->cheRecFile->isChecked() == true){
        QByteArray byte = m_serialPort.readAll();//全部读取
        //        m_serialPort.
        m_recByteArray += byte;//添加到原生二进制字符串中去

        ui->textMainAccept->insertPlainText(byte);
        ui->btnSerialLogSave->setEnabled(true);
        ui->btnSerialSave->setEnabled(true);

        m_recCountSerial += byte.size();//接收计数
        m_statueLab5.setText(QString::asprintf("%d",m_recCountSerial));
        return;
    }


    //以下代码为正常接收,而不是接收文件
    QByteArray byte = m_serialPort.readAll();//先获取接收内容,再加工



    QString resultStr = byte;
    if(ui->radioAcceptAscll->isChecked() == true){

        resultStr = byte;

    }else if(ui->radioAcceptHEX->isChecked() == true){//如果勾选接收为16进制
        static QRegularExpression re("\\s");
        resultStr = resultStr.simplified().remove(re);

        if(resultStr.size()%2 != 0){//自动补全
            resultStr.insert(0,'0');
        }

        QString hexStr;
        bool ok;
        for(int i = 0;i < resultStr.size()/2;++i){
            hexStr += resultStr.mid(2*i,2).toInt(&ok,16);//切割字符串
        }

        resultStr = hexStr;//获得hex格式的内容
    }

    //以下代码用于二次加工
    ui->btnSerialLogSave->setEnabled(true);
    ui->btnSerialSave->setEnabled(true);

    m_originalAcceptString += resultStr;//写入原生字符串

    m_recCountSerial += resultStr.size();//接收数据长度计数
    m_statueLab5.setText(QString::asprintf("%d",m_recCountSerial));//状态栏显示


    if(ui->radioAcceptAscll->isChecked() == true){//以ascll编码形式接收
        resultStr.prepend(tr("[Ascll 接收]:"));
    }else if(ui->radioAcceptHEX->isChecked() == true){//以hex编码形式接收
        resultStr.prepend(tr("[Hex 接收]:"));
    }

    if(ui->cheAcceptShowTime->isChecked() == true){//如果勾选显示时间
        resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
    }
    if(ui->cheAcceptAutoLine->isChecked() == true){//如果勾选自动换行
        ui->textMainAccept->append(resultStr);
        return;
    }

    ui->textMainAccept->insertPlainText(resultStr);
}


void MainWindow::on_actClear_triggered()
{

}


void MainWindow::on_btnClearSendText_clicked()
{
    ui->textMainSend->clear();
    m_reSendTimer.stop();//清空发送框会停止计时器
    if(ui->cheReSend->isChecked() == true){
        ui->btnSend->setText(tr("已关闭"));
        ui->btnSend->setIcon(QIcon(":/img/loseConnect.png"));
    }else{
        ui->btnSend->setText(tr("发送"));
        ui->btnSend->setIcon(QIcon(""));
    }
}

void MainWindow::on_timer_out()
{
    QString sendStr = ui->textMainSend->toPlainText();
    QString resultStr;

    if(ui->radioSendHEX->isChecked() == true){//如果勾选发送为16进制
        static QRegularExpression re("\\s");
        sendStr = sendStr.simplified().remove(re);

        if(sendStr.size()%2 != 0){//自动补全
            sendStr.insert(0,'0');
        }

        resultStr = sendStr;//获得hex格式的内容

    }else{
        resultStr = sendStr;//获得ascll格式的内容
    }

    m_serialPort.write(resultStr.toUtf8());//发送内容数据
    m_sendCountSerial += resultStr.size();//发送计数
    m_statueLab4.setText(QString::asprintf("%d",m_sendCountSerial));

    //以下代码用于UI显示加工内容
    if(ui->cheAccoptShowSend->isChecked() == true){//如果勾选显示发送框
        if(ui->radioSendAscll->isChecked() == true){//以ascll编码形式发送
            resultStr.prepend(tr("[Ascll 发送]:"));
        }else if(ui->radioSendHEX->isChecked() == true){//以hex编码形式发送
            resultStr.prepend(tr("[Hex 发送]:"));
        }

        if(ui->cheAcceptShowTime->isChecked() == true){//如果勾选显示时间
            resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
        }
        if(ui->cheAcceptAutoLine->isChecked() == true){//如果勾选自动换行
            ui->textMainAccept->append(resultStr);
            return;
        }
        ui->textMainAccept->insertPlainText(resultStr);
    }
}


void MainWindow::on_spinBoxSendTime_valueChanged(int arg1)
{
    m_reSendInterval = arg1;//更新定时器触发间隔
    m_reSendTimer.setInterval(m_reSendInterval);
}


void MainWindow::on_cheReSend_stateChanged(int arg1)
{
    if(arg1 == Qt::Unchecked){//关闭重复发送
        if(m_reSendTimer.isActive() == true){//如果取消勾选重复发送时正在重复发送
            ui->textMainAccept->append(tr("重复发送停止."));
        }
        m_reSendTimer.stop();
        ui->btnSend->setText(tr("发送"));
        ui->btnSend->setIcon(QIcon(""));

    }else if(arg1 == Qt::Checked){//打开重复发送
        m_reSendTimer.stop();
        ui->btnSend->setText(tr("已关闭"));
        ui->btnSend->setIcon(QIcon(":/img/loseConnect.png"));

    }
}

void MainWindow::setSetingVisiable(bool visiable)
{
    if(visiable == true){
        ui->cheAcceptAutoLine->show();
        ui->cheAcceptShowTime->show();
        ui->cheAccoptShowSend->show();
        ui->cheRecFile->show();

    }
    ui->cheAcceptAutoLine->hide();
    ui->cheAcceptShowTime->hide();
    ui->cheAccoptShowSend->hide();
    ui->cheRecFile->hide();
    ;
}

void MainWindow::on_reRsend_checked()
{

}


void MainWindow::on_textMainSend_textChanged()
{
    //管理发送框清理按钮是否可用
    if(ui->textMainSend->toPlainText().isEmpty() == true){
        ui->btnClearSendText->setEnabled(false);
    }else{
        ui->btnClearSendText->setEnabled(true);
    }

    //只有当发送框有文本并且当前端口已连接时才能与发送按钮互动
    if(!(ui->textMainSend->toPlainText().isEmpty() || ui->textMainSend->toPlainText().isNull() || m_isConnect == false)){
        ui->btnSend->setEnabled(true);

    }else{

        ui->btnSend->setEnabled(false);

        if(ui->cheReSend->isChecked() == true){
            if(m_reSendTimer.isActive() == true){
                ui->textMainAccept->append(tr("重复发送结束."));
            }
            ui->btnSend->setText(tr("已关闭"));
            ui->btnSend->setIcon(QIcon(":/img/loseConnect.png"));

        }else if(ui->cheReSend->isChecked() == false){
            ui->btnSend->setText(tr("发送"));
            ui->btnSend->setIcon(QIcon(""));

        }

        m_reSendTimer.stop();
    }


}


void MainWindow::on_btnClearAcceptText_clicked()
{
    if(ui->textMainAccept->toPlainText().isEmpty() == true){
        ui->btnClearAcceptText->setEnabled(false);

    }else{
        ui->textMainAccept->clear();

        ui->btnClearAcceptText->setEnabled(false);
    }

    m_originalAcceptString = "";//清空原生字符串接收内容
    ui->btnSerialLogSave->setEnabled(false);
    ui->btnSerialSave->setEnabled(false);

    //清空发送接收计数
    m_recCountSerial = 0;
    m_sendCountSerial = 0;
    m_statueLab5.setText("0");
    m_statueLab4.setText("0");
    m_recByteArray.clear();//清除接受的二进制原生字符串
}


void MainWindow::on_textMainAccept_textChanged()
{
    if(ui->textMainAccept->toPlainText().isEmpty() == false){
        ui->btnClearAcceptText->setEnabled(true);
    }else{
        ui->btnClearAcceptText->setEnabled(false);
    }

    ui->textMainAccept->moveCursor(QTextCursor::End);//接受框内容改变就将滑动条拿到最底部
}


void MainWindow::on_combFlowControl_currentIndexChanged(int index)
{
    Q_UNUSED(index);
    //初始化流控
    if(ui->combFlowControl->currentIndex() == 0){
        m_serialPort.setFlowControl(QSerialPort::NoFlowControl);//无流控
    }else if(ui->combFlowControl->currentIndex() == 1){
        m_serialPort.setFlowControl(QSerialPort::SoftwareControl);//软件流控
    }else if(ui->combFlowControl->currentIndex() == 2){
        m_serialPort.setFlowControl(QSerialPort::HardwareControl);//硬件流控
    }
}


void MainWindow::on_btnBrowerFile_clicked()
{
    QString filePath =QFileDialog::getOpenFileName(0,tr("请选择文件"),QDir::homePath(),"all(*.*);;txt(*.txt);;hex(*.hex);;dat(*.dat);;ini(*.ini)");//选择文件
    if(filePath.isEmpty() || filePath.isNull()){//检查路径是否可用
        return;
    }else{//路径可用
        ui->editFilePath->setText(filePath);//填充路径框
        ui->progressBarSendFile->setValue(0);
    }

    if(m_isConnect == true){//检测串口是否已经连接
        ui->btnSendFile->setEnabled(true);//文件发送按钮可以互动
    }
}


void MainWindow::on_editFilePath_textChanged(const QString &arg1)
{
    Q_UNUSED(arg1);
    ui->progressBarSendFile->setValue(0);
    if(ui->editFilePath->text().isEmpty() || ui->editFilePath->text().isNull() || m_isConnect == false){
        ui->btnSendFile->setEnabled(false);//文件发送按钮不可互动
    }else{
        ui->btnSendFile->setEnabled(true);//文件发送按钮可以互动
    }
}


void MainWindow::on_btnSendFile_clicked()
{
    m_sendFile.setFileName(ui->editFilePath->text());//获取文件路径框的文件路径
    if(m_sendFile.exists() == false || m_sendFile.open(QIODevice::ReadOnly) == false){//如果路径不可用,或者文件打开失败.
        QMessageBox::warning(0,tr("警告"),tr("文件打开失败,请检查路径是否正确."));
        return;
    }

    //以下代码用于发送文件
    ui->btnSerialLogSave->setEnabled(true);

    ui->btnSendFile->setEnabled(false);
    ui->btnBrowerFile->setEnabled(false);
    ui->btnSendFile->setText(tr("正在发送"));
    ui->progressBarSendFile->setValue(0);
    ui->progressBarSendFile->setMaximum(m_sendFile.size());//设置发送进度条最大值
    ui->btnConnect->setEnabled(false);
    ui->btnSend->setEnabled(false);

    ui->textMainAccept->append(tr("文件开始发送..."));
    for(int i = 0;i < m_sendFile.size();i += m_sendFileSignalSize){//循环读取文件内容并发送

        m_serialPort.write(m_sendFile.read(m_sendFileSignalSize),m_sendFileSignalSize);
        ui->progressBarSendFile->setValue(ui->progressBarSendFile->value() + m_sendFileSignalSize);
        ui->textMainAccept->append(QString::asprintf("%.2f%%",((ui->progressBarSendFile->value()/(double)m_sendFile.size()) * 100))+tr("  当前:") +QString::asprintf("%d",ui->progressBarSendFile->value())+tr("  总长度:")+QString::asprintf("%d",(int)m_sendFile.size()));

    }
    m_statueLab4.setText(QString::asprintf("%d",(int)(m_statueLab4.text().toInt() + m_sendFile.size())));//更新状态栏

    //文件发送完成后执行以下代码
    ui->textMainAccept->append(QString::asprintf("100%%")+tr("  当前:") +QString::asprintf("%d",(int)m_sendFile.size())+tr("  总长度:")+QString::asprintf("%d",(int)m_sendFile.size()));
    ui->textMainAccept->append(tr("文件发送完成!"));
    ui->progressBarSendFile->setValue(ui->progressBarSendFile->maximum());
    ui->btnSendFile->setEnabled(true);
    ui->btnBrowerFile->setEnabled(true);
    ui->btnSendFile->setText(tr("发送"));
    ui->btnConnect->setEnabled(true);
    if(!(ui->textMainSend->toPlainText().isEmpty() || ui->textMainSend->toPlainText().isNull() || m_isConnect == false)){
        ui->btnSend->setEnabled(true);
    }
}


void MainWindow::on_actSerialPortWindow_triggered()
{
    ui->stackedWidget->setCurrentWidget(ui->pagSerial);
}


void MainWindow::on_actNetworkWindow_triggered()
{
    ui->stackedWidget->setCurrentWidget(ui->pagNetwork);
}

void MainWindow::on_Window_changed(QAction *action)
{
    ui->actSerialPortWindow->setChecked(false);
    ui->actNetworkWindow->setChecked(false);
    action->setChecked(true);
    if(action == ui->actNetworkWindow ){//切换界面时更新状态栏的发送设置标签,切换到网络调试界面
        if(m_reSendTimer.isActive() == true){//如果切换到网络调试界面时,串口调试正在重复发送信息
            ui->btnSend->setText(tr("已关闭"));
            ui->btnSend->setIcon(QIcon(":/img/loseConnect.png"));
            m_reSendTimer.stop();//关闭定时器
            ui->textMainAccept->append(tr("重复发送结束."));
        }

        //m_label0
        m_statueLab0.setText("网络通信");

        //m_label1
        if(m_isConnectNet == true){
            m_statueLab1.setText(tr("状态:已打开"));
        }else{
            m_statueLab1.setText(tr("状态:已关闭"));
        }

        //m_label2
        if(ui->combProtocolNet->currentIndex() == 0){//tcp服务器
            m_statueLab2.setText(tr("协议:TCPServer"));
        }else if(ui->combProtocolNet->currentIndex() == 1){//tcp客户端
            m_statueLab2.setText(tr("协议:TCPClient"));
        }else if(ui->combProtocolNet->currentIndex() == 2){//udp通信
            m_statueLab2.setText(tr("协议:UDP"));
        }

        //m_label3
        if(ui->radioSendAscllNet->isChecked() == true){//如果勾选ascll发送
            m_statueLab3.setText(tr("发送设置:Ascll"));
        }else{//如果勾选hex发送
            m_statueLab3.setText(tr("发送设置:Hex"));
        }

        //m_lab4
        m_statueLab4.setText(QString::asprintf("%d",m_sendCountNet));

        //m_label5
        m_statueLab5.setText(QString::asprintf("%d",m_recCountNet));

    }

    else if(action == ui->actSerialPortWindow){//切换到串口调试界面
        if(m_timerReSendNet->isActive() == true){//如果切换到串口调试界面时,网络调试正在重复发送信息
            ui->btnSendNet->setText(tr("已关闭"));
            ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
            m_timerReSendNet->stop();//关闭定时器
            ui->textRecNet->append(tr("重复发送结束."));
        }

        //m_label0
        m_statueLab0.setText(tr("串口通信"));

        //m_label1
        if(m_isConnect == true){
            m_statueLab1.setText(tr("状态:已打开"));
        }else{
            m_statueLab1.setText(tr("状态:已关闭"));
        }

        //m_label2
        m_statueLab2.setText(tr("串口:")+ui->combSerialPort->currentText());

        //m_label3
        if(ui->radioSendAscll->isChecked() == true){//如果勾选ascll发送
            m_statueLab3.setText(tr("发送设置:Ascll"));
        }else{//如果勾选hex发送
            m_statueLab3.setText(tr("发送设置:Hex"));
        }

        //m_lab4
        m_statueLab4.setText(QString::asprintf("%d",m_sendCountSerial));

        //m_label5
        m_statueLab5.setText(QString::asprintf("%d",m_recCountSerial));
    }
}


void MainWindow::on_btnSerialSave_clicked()
{
    QString savePath = QFileDialog::getSaveFileName(0,tr("请选择保存位置"),QDir::homePath(),"all(*.*);;txt(*.txt);;hex(*.hex);;dat(*.dat);;ini(*.ini)");
    QFile file(savePath);

    if(file.open(QIODevice::WriteOnly) == false){//如果文件打开失败
        QMessageBox::warning(0,tr("警告"),tr("文件保存失败!"));
        return;
    }

    //以下代码实现保存功能
    if(ui->cheRecFile->isChecked() == true){//如果勾选接收为文件则保存为文件
        file.write(m_recByteArray);
        file.close();
        return;
    }
    file.write(m_originalAcceptString.toUtf8());
    file.close();
}


void MainWindow::on_btnSerialLogSave_clicked()
{
    QString savePath = QFileDialog::getSaveFileName(0,tr("请选择保存位置"),QDir::homePath(),"txt(*.txt);;all(*.*)");
    QFile file(savePath);

    if(file.open(QIODevice::WriteOnly) == false){//如果文件打开失败
        QMessageBox::warning(0,tr("警告"),tr("日志保存失败!"));
        return;
    }

    //以下代码实现保存功能
    //    file.write(ui->textMainAccept->toPlainText().toUtf8());
    QTextStream aStream(&file);
    aStream << ui->textMainAccept->toPlainText();
    file.close();
}


void MainWindow::on_actCustomBundRate_triggered()
{
    int newBandRate = QInputDialog::getInt(0,tr("请输入自定义波特率"),tr("请输入自定义波特率"));
    ui->combBaudRate->addItem(QString::asprintf("%d",newBandRate));
    ui->combBaudRate->setCurrentIndex(ui->combBaudRate->count() - 1);
    ui->combBaudRate->currentTextChanged(ui->combBaudRate->currentText());
}


void MainWindow::on_radioSendHEX_clicked(bool checked)
{
    if(checked == true){
        m_statueLab3.setText(tr("发送设置:Hex"));


        //发送框内容进制转换
        QByteArray temp = ui->textMainSend->toPlainText().toUtf8();
        ui->textMainSend->clear();
        QString resultStr;

        resultStr = QString::fromUtf8(temp.toHex());
        for(int i = resultStr.size() - 2;i > 0; --i){//插入空格分隔符
            if(i % 2 == 0){
                resultStr.insert(i," ");
            }
        }
        ui->textMainSend->append(resultStr);

    }else{
        m_statueLab3.setText(tr("发送设置:Ascll"));
    }
}


void MainWindow::on_radioSendAscll_clicked(bool checked)
{
    if(checked == true){
        m_statueLab3.setText(tr("发送设置:Ascll"));

        //发送框内容进制转换
        QString temp = ui->textMainSend->toPlainText();
        ui->textMainSend->clear();

        static QRegularExpression re("\\s");
        temp = temp.simplified().remove(re);

        if(temp.size()%2 != 0){//自动补全
            temp.insert(0,'0');
        }

        QString resultStr;

        bool ok;
        for(int i = 0;i < temp.size()/2;++i){
            resultStr += temp.mid(2*i,2).toInt(&ok,16);//切割字符串
        }

        ui->textMainSend->append(resultStr);
    }else{
        m_statueLab3.setText(tr("发送设置:Hex"));
    }
}


void MainWindow::on_actSetFont_triggered()
{
    bool ok = false;
    QFont newFont = QFontDialog::getFont(&ok);
    if(ok == true){
        this->setFont(newFont);
    }
}


void MainWindow::on_actSetBackColor_triggered()
{
    QColor newColor = QColorDialog::getColor();
    if(newColor.isValid() == true){
        ui->textMainAccept->setStyleSheet("background-color: rgb("+QString::asprintf("%d",newColor.red())+", "+QString::asprintf("%d",newColor.green())+", "+QString::asprintf("%d",newColor.blue())+");");
        ui->textMainSend->setStyleSheet("background-color: rgb("+QString::asprintf("%d",newColor.red())+", "+QString::asprintf("%d",newColor.green())+", "+QString::asprintf("%d",newColor.blue())+");");
    }
}


void MainWindow::on_actDefaultSetting_triggered()
{
    QColor newColor(Qt::white);
    ui->textMainAccept->setStyleSheet("background-color: rgb("+QString::asprintf("%d",newColor.red())+", "+QString::asprintf("%d",newColor.green())+", "+QString::asprintf("%d",newColor.blue())+");");
    ui->textMainSend->setStyleSheet("background-color: rgb("+QString::asprintf("%d",newColor.red())+", "+QString::asprintf("%d",newColor.green())+", "+QString::asprintf("%d",newColor.blue())+");");

    QFont newFont("黑体",11);
    this->setFont(newFont);
}


void MainWindow::on_btnPauseAccept_clicked()
{
    if(m_isConnect == true && m_isAcceptRec == true ){
        ui->btnPauseAccept->setText("拒收");
        ui->btnPauseAccept->setIcon(QIcon(":/img/loseConnect.png"));
        m_isAcceptRec = false;//修改为拒收状态
        disconnect(&m_serialPort,SIGNAL(readyRead()),this,SLOT(on_serialPort_readyRead()));//断开接受信息槽函数
    }else if(m_isConnect == true && m_isAcceptRec == false){
        m_serialPort.readAll();//将接收缓冲区清空

        ui->btnPauseAccept->setText("接收");
        ui->btnPauseAccept->setIcon(QIcon(":/img/getConnect.png"));
        m_isAcceptRec = true;//修改为接收状态
        connect(&m_serialPort,SIGNAL(readyRead()),this,SLOT(on_serialPort_readyRead()));//连接接受信息槽函数
    }
}


void MainWindow::on_pushButton_clicked()
{

}

void MainWindow::iniNetWindow()
{
    //往地址combox中添加ipv4地址
    QList<QHostAddress> addHostList = getIPv4Address();
    for(int i = 0 ;i < addHostList.count(); ++i){
        ui->combHostNet->addItem(addHostList.at(i).toString());
    }
}

QList<QHostAddress> MainWindow::getIPv4Address()
{
    QList<QHostAddress> addressList = QHostInfo::fromName(QHostInfo::localHostName()).addresses();//获取地址列表
    if(!addressList.isEmpty()){//检测地址列表是否为空
        for(int i = addressList.count() - 1; i >= 0; --i){//遍历地址列表
            if(addressList.at(i).protocol() != QAbstractSocket::IPv4Protocol){//去除非ipv4地址
                addressList.removeAt(i);
            }
        }
    }
    return addressList;
}


void MainWindow::on_combProtocolNet_currentIndexChanged(int index)//index:0表示tcp服务器,1表示tcp客户端,2表示udp通信
{
    //m_label2
    if(index == 0){//tcp服务器
        m_statueLab2.setText(tr("协议:TCPServer"));
    }else if(index == 1){//tcp客户端
        m_statueLab2.setText(tr("协议:TCPClient"));
    }else if(index == 2){//udp通信
        m_statueLab2.setText(tr("协议:UDP"));
    }



    if(index == 0){//tcp服务器
        ui->btnListenNet->setText(tr("已关闭"));
        m_statueLab1.setText(tr("状态:未连接"));
        ui->labHostNet->setText("本机地址:");
        ui->labPortNet->setText("本机端口:");

        ui->combHostNet->clear();//清理原有item
        QList<QHostAddress> addHostList = getIPv4Address();//重新扫描地址
        for(int i = 0 ;i < addHostList.count(); ++i){
            ui->combHostNet->addItem(addHostList.at(i).toString());
        }

        ui->btnListenNet->setEnabled(true);
        ui->groupUdpCast->setEnabled(false);

        ui->btnNewTcpServiceNet->setEnabled(false);
        ui->btnNewTcpServiceNet->hide();


        //释放进程资源,和线程资源
        for(int i = m_tcpProgerssList.count() - 1;i >= 0 ;--i){
            if(m_tcpProgerssList.at(i) != NULL){
                m_tcpThreadList.at(i)->quit();
                m_tcpThreadList.at(i)->wait();
                delete m_tcpProgerssList.at(i);
//                emit deleteProgress(i);
                m_tcpThreadList.at(i)->deleteLater();

            }
        }

//        释放窗口资源
        for(int i = m_tcpWidgetList.count() - 1;i >= 0 ;--i){
            if(m_tcpWidgetList.at(i) != NULL){
                m_tcpWidgetList.at(i)->deleteLater();

            }
        }

        //重置资源列表
        m_tcpProgerssList.clear();
        m_tcpThreadList.clear();
        m_tcpWidgetList.clear();
        m_tcpOriRec.clear();

    }else if(index == 1){//tcp客户端
        ui->btnListenNet->setText(tr("已关闭"));
        m_statueLab1.setText(tr("状态:未连接"));
        ui->labHostNet->setText("目标地址:");
        ui->labPortNet->setText("目标端口:");
        ui->combHostNet->clear();//清理所有ipv4地址
        ui->combHostNet->setCurrentText(getIPv4Address().at(0).toString());//设置默认为本机地址

        ui->btnListenNet->setEnabled(false);
        ui->groupUdpCast->setEnabled(false);

        ui->btnNewTcpServiceNet->setEnabled(true);
        ui->btnNewTcpServiceNet->show();


        //释放进程资源,和线程资源
        for(int i = m_tcpProgerssList.count() - 1;i >= 0 ;--i){
            if(m_tcpProgerssList.at(i) != NULL){
                m_tcpThreadList.at(i)->quit();
                m_tcpThreadList.at(i)->wait();
                delete m_tcpProgerssList.at(i);
//                emit deleteProgress(i);
                m_tcpThreadList.at(i)->deleteLater();

            }
        }

//        释放窗口资源
        for(int i = m_tcpWidgetList.count() - 1;i >= 0 ;--i){
            if(m_tcpWidgetList.at(i) != NULL){
                m_tcpWidgetList.at(i)->deleteLater();

            }
        }

        //重置资源列表
        m_tcpProgerssList.clear();
        m_tcpThreadList.clear();
        m_tcpWidgetList.clear();
        m_tcpOriRec.clear();

    }else if(index == 2){//udp通信

        m_statueLab1.setText(tr("状态:未绑定"));
        ui->labHostNet->setText("本机地址:");
        ui->labPortNet->setText("本机端口:");
        ui->btnListenNet->setText(tr("未绑定"));
        ui->combHostNet->clear();//清理原有item

        ui->btnNewTcpServiceNet->setEnabled(false);
        ui->btnNewTcpServiceNet->hide();

        ui->groupUdpCast->setEnabled(true);

        QList<QHostAddress> addHostList = getIPv4Address();//重新扫描地址
        for(int i = 0 ;i < addHostList.count(); ++i){
            ui->combHostNet->addItem(addHostList.at(i).toString());
        }

        //判定udp通信按钮是否可互动
        ui->btnListenNet->setEnabled(true);
        if(ui->combUdpCastModeNet->currentIndex() == 2){//如果当前为udp组播模式则连接按钮不可互动
            ui->btnListenNet->setEnabled(false);
        }
        ui->btnJoinBroadMulticastNet->setEnabled(false);
        if(ui->combUdpCastModeNet->currentIndex() == 2 && !ui->editTargetHostNet->text().isEmpty() && !ui->editTargetPortNet->text().isEmpty()){
            ui->btnJoinBroadMulticastNet->setEnabled(true);//如果当前端口已经绑定,并且用户选择组播模式,并且目标端口和地址不为空
        }
    }
}


void MainWindow::on_btnListenNet_clicked()
{
    //第一部分代码用于tcp服务器
    if(ui->combProtocolNet->currentIndex() == 0 && m_isConnectNet == false){//如果当前为服务器配置,并且没有连接,就启动tcp服务器监听
        QString IP = ui->combHostNet->currentText();
        int port = ui->editPortNet->text().toInt();
        QRegExp re("^(?:(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])$");
        if(!re.exactMatch(IP) || ui->editPortNet->text().isEmpty() || ui->editPortNet->text().toInt() < 0 || ui->editPortNet->text().toInt() > 65535){//检测地址端口号是否规范
            QMessageBox::warning(0,tr("警告"),tr("服务器配置出错"));
            return;
        } else{
            QHostAddress addr(IP);
            if(m_tcpServer->listen(addr,port) == false){//尝试启动监听
                QMessageBox::warning(0,tr("警告"),tr("启动监听失败,此端口可能已经被占用."));
                return;
            }
            m_isConnectNet = true;//监听启动后就设置对应的成员变量为真
            m_statueLab1.setText(tr("状态:已打开"));

            ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+IP+tr(" 端口:")+QString::asprintf("%d",port)+tr(" 开始监听..."));
            ui->btnListenNet->setText(tr("已打开"));
            ui->btnListenNet->setIcon(QIcon(":/img/getConnect.png"));
            ui->combProtocolNet->setEnabled(false);//设置对应的按钮不可互动
            ui->combHostNet->setEnabled(false);
            ui->editPortNet->setEnabled(false);
            ui->btnUpdateNet->setEnabled(false);


        }
    }else if(ui->combProtocolNet->currentIndex() == 0 && m_isConnectNet == true){//如果当前为服务器配置,并且以经连接,就断开tcp服务器监听


        if(m_timerReSendNet->isActive() == true){//如果关闭监听时正在重复发送+

            if(ui->tabWidgetNet->currentIndex()!=0){
                int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
                for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                    if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                        index = i;
                        break;
                    }
                }

                m_tcpWidgetList.at(index)->append(tr("重复发送结束."));

            }else{
                ui->textRecNet->append(tr("重复发送结束."));
            }

        }
        m_timerReSendNet->stop();
        ui->btnSendNet->setText(tr("已关闭"));
        ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));


        m_tcpServer->close();//关闭监听
        m_statueLab1.setText(tr("状态:已关闭"));


        m_isConnectNet = false;//监听关闭后就设置对应的成员变量为假
        ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("已关闭监听..."));
        ui->btnListenNet->setText(tr("已关闭"));
        ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
        ui->combProtocolNet->setEnabled(true);//设置对应的按钮可以互动
        ui->combHostNet->setEnabled(true);
        ui->editPortNet->setEnabled(true);
        ui->btnUpdateNet->setEnabled(true);

        ui->btnSendNet->setEnabled(false);



        //释放进程资源,和线程资源
        for(int i = m_tcpProgerssList.count() - 1;i >= 0 ;--i){
            if(m_tcpProgerssList.at(i) != NULL){
                m_tcpThreadList.at(i)->quit();
                m_tcpThreadList.at(i)->wait();
                delete m_tcpProgerssList.at(i);
//                emit deleteProgress(i);
                m_tcpThreadList.at(i)->deleteLater();

            }
        }

//        释放窗口资源
        for(int i = m_tcpWidgetList.count() - 1;i >= 0 ;--i){
            if(m_tcpWidgetList.at(i) != NULL){
                m_tcpWidgetList.at(i)->deleteLater();

            }
        }

        //重置资源列表
        m_tcpProgerssList.clear();
        m_tcpThreadList.clear();
        m_tcpWidgetList.clear();
        m_tcpOriRec.clear();

    }

    //第二部分代码用于tcp客户端
    else if(ui->combProtocolNet->currentIndex() == 1 && m_isConnectNet == false){//如果tcp客户端没有连接则打开连接



    }else if(ui->combProtocolNet->currentIndex() == 1 && m_isConnectNet == true){//如果tcp客户端已经连接则断开连接

        int index = getThreadIndexNet();
        ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+m_tcpProgerssList.at(index)->m_peerAddress+tr(" 已断开连接"));


        //释放线程和程序占用的资源
        m_tcpThreadList.at(index)->quit();
        m_tcpThreadList.at(index)->wait();
        delete m_tcpProgerssList.at(index);
    //    emit goDeleteProgress(index);
    //////////
        m_tcpProgerssList.removeAt(index);
        mytcpprogress*  p;
        p = NULL;
        m_tcpProgerssList.insert(index,p);
    //////////

        m_tcpThreadList.at(index)->deleteLater();

        m_tcpWidgetList.at(index)->deleteLater();
        ///////
        m_tcpWidgetList.removeAt(index);
        QTextBrowser* b;
        b = NULL;
        m_tcpWidgetList.insert(index,b);
        ///////

        ui->tabWidgetNet->setCurrentIndex(0);//断开连接后回到main界面

        ui->btnListenNet->setText(tr("已关闭"));
        ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
        ui->btnListenNet->setEnabled(false);

        if(m_timerReSendNet->isActive() == true){//如果断开连接时,定时器正在运行并且断开连接的窗口是当前对话的窗口则关闭重复发送

            m_timerReSendNet->stop();
            ui->btnSendNet->setText(tr("已关闭"));
            ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));

        }

        //如果当前为tcp客户端,设置连接按钮为关闭状态

        ui->btnListenNet->setText(tr("已关闭"));
        ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
        ui->btnListenNet->setEnabled(false);

        //判断界面列表是否全为空,进而判断当前是否还有连接存在
        bool widgetAllIsNull = false;
        for(int i = 0; i < m_tcpWidgetList.count() ; ++i){
            if(m_tcpWidgetList.at(i) != NULL){
                widgetAllIsNull = false;
                break;
            }
            widgetAllIsNull = true;
        }
        if(widgetAllIsNull == true){//如果当前界面只有main,没有其他窗口
            ui->combProtocolNet->setEnabled(true);//设置对应的按钮可互动

            //释放进程资源,和线程资源
            for(int i = m_tcpProgerssList.count() - 1;i >= 0 ;--i){
                if(m_tcpProgerssList.at(i) != NULL){
                    m_tcpThreadList.at(i)->quit();
                    m_tcpThreadList.at(i)->wait();
                    delete m_tcpProgerssList.at(i);
    //                emit deleteProgress(i);
                    m_tcpThreadList.at(i)->deleteLater();

                }
            }

    //        释放窗口资源
            for(int i = m_tcpWidgetList.count() - 1;i >= 0 ;--i){
                if(m_tcpWidgetList.at(i) != NULL){
                    m_tcpWidgetList.at(i)->deleteLater();

                }
            }

            //重置资源列表
            m_tcpProgerssList.clear();
            m_tcpThreadList.clear();
            m_tcpWidgetList.clear();
            m_tcpOriRec.clear();
        }



    }

    //第三部分用于udp通信
    else if(ui->combProtocolNet->currentIndex() == 2 && m_isBindNet == false){//如果udp通信已经关闭
        //检测本地地址端口是否规范
        QString IP = ui->combHostNet->currentText();
        int port = ui->editPortNet->text().toInt();
        QRegExp re("^(?:(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])$");
        if(!re.exactMatch(IP) || ui->editPortNet->text().isEmpty() || ui->editPortNet->text().toInt() < 0 || ui->editPortNet->text().toInt() > 65535){//检测地址端口号是否规范
            QMessageBox::warning(0,tr("警告"),tr("本机端口地址配置出错."));
            return;
        }

        if(m_udpSocket->isOpen() == true){//如果已经绑定则先断开原有绑定
            m_udpSocket->abort();
        }
        QHostAddress addRess(IP);
        if(m_udpSocket->bind(addRess,port) == false){//如果绑定失败
            QMessageBox::warning(0,tr("警告"),tr("本机端口地址绑定失败."));
            return;
        }

        //如果绑定本地端口地址成功
        m_isBindNet = true;//设置对应的成员变量值
        ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] 已绑定本地端口地址."));
        ui->btnListenNet->setText(tr("已绑定"));
        ui->btnListenNet->setIcon(QIcon(":/img/getConnect.png"));
        m_statueLab1.setText(tr("状态:已绑定"));
        ui->combProtocolNet->setEnabled(false);//设置对应的按钮不可互动
        ui->combHostNet->setEnabled(false);
        ui->editPortNet->setEnabled(false);
        ui->btnUpdateNet->setEnabled(false);

        //设置udp通信模式选择功能不可互动
        ui->combUdpCastModeNet->setEnabled(false);

        //判定发送按钮是否可以互动
        if(m_isBindNet == true && !ui->textSendNet->toPlainText().isEmpty()){
            ui->btnSendNet->setEnabled(true);
        }

    }else if(ui->combProtocolNet->currentIndex() == 2 && m_isBindNet == true){//如果udp通信已经打开

        m_udpSocket->abort();//关闭当前udp套接字连接
        ui->btnSendNet->setEnabled(false);
        m_isBindNet = false;//设置对应的成员变量值
        ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] 已解除本地端口地址绑定."));
        ui->btnListenNet->setText(tr("未绑定"));
        ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
        m_statueLab1.setText(tr("状态:未绑定"));
        ui->combProtocolNet->setEnabled(true);//设置对应的按钮可以互动
        ui->combHostNet->setEnabled(true);
        ui->editPortNet->setEnabled(true);
        ui->btnUpdateNet->setEnabled(true);

        //设置udp通信模式选择功能可以互动
        ui->combUdpCastModeNet->setEnabled(true);
    }
}


void MainWindow::on_actUpdateNet_triggered()
{
    if(ui->combProtocolNet->currentIndex() == 0 ){//tcp服务器
        ui->combHostNet->clear();//清理原有item
        //添加新扫描的地址
        QList<QHostAddress> addHostList = getIPv4Address();
        for(int i = 0 ;i < addHostList.count(); ++i){
            ui->combHostNet->addItem(addHostList.at(i).toString());
        }
    }else if(ui->combProtocolNet->currentIndex() == 1){//tcp客户端
        ui->combHostNet->setCurrentText("");//清理输入
        ui->combHostNet->setCurrentText(getIPv4Address().at(0).toString());//设置默认为本机地址
    }else if(ui->combProtocolNet->currentIndex() == 2){//udp通信
        ui->combHostNet->clear();//清理原有item
        //添加新扫描的地址
        QList<QHostAddress> addHostList = getIPv4Address();
        for(int i = 0 ;i < addHostList.count(); ++i){
            ui->combHostNet->addItem(addHostList.at(i).toString());
        }
    }

}

void MainWindow::on_socket_stateChanged(QAbstractSocket::SocketState state)
{
    if(ui->combProtocolNet->currentIndex() == 0 && state == QAbstractSocket::SocketState::UnconnectedState){//当做为服务器丢失连接时
        ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+m_tcpSocket->peerAddress().toString()+tr(" 主机名:")+m_tcpSocket->peerName()+tr(" 已断开连接."));
    }
    else if(ui->combProtocolNet->currentIndex() == 1 && state == QAbstractSocket::SocketState::UnconnectedState){

    }
}

void MainWindow::on_socket_connected(qintptr socket)
{
    if(ui->combProtocolNet->currentIndex() == 0){//当socket作为服务器主机接收客户端连接时
//        m_tcpSocket = NULL;//置空socket
//        m_tcpSocket = m_tcpServer->nextPendingConnection();//获取socket
//        if(m_tcpSocket == NULL){//如果socket获取客户端连接失败
//            QMessageBox::warning(0,tr("警告"),tr("客户端连接出错."));
//            m_tcpSocket = new QTcpSocket(this);
//            return;
//        }
//        connect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(on_tcpSocket_readyRead()));//连接tcpsocket读写槽函数
//        //以下代码在服务器socket正常连接客户端时执行
//        m_timerNet->start();//作为客服端连接成功后打开保活计时器
//        ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+m_tcpSocket->peerAddress().toString()+tr(" 已连接本机 ..."));

//        ui->btnSendNet->setEnabled(false);
//        if(!(ui->textSendNet->toPlainText().isEmpty() || ui->textSendNet->toPlainText().isNull() || m_isConnectNet == false) && m_tcpSocket->state() == QAbstractSocket::ConnectedState){
//            ui->btnSendNet->setEnabled(true);
//        }

        //创建实例
        mytcpprogress* pro = new mytcpprogress;
        QThread* thr = new QThread;
        pro->moveToThread(thr);//移动程序到线程
        thr->start();//启动线程
        QTextBrowser* txt = new QTextBrowser;
        m_tcpProgerssList.append(pro);
        m_tcpThreadList.append(thr);
        m_tcpWidgetList.append(txt);
        m_tcpOriRec.append("");

        txt->setFont(this->font());//新窗口字体和主窗口一致

        connect(txt,SIGNAL(textChanged()),txt,SLOT([=](){txt->moveCursor(QTextCursor::End)}));//当有新内容时自动移动到最新的地方

        //主线程控制子线程创建套接字连接
        connect(this,SIGNAL(createTcpConnect(qintptr,int)),pro,SLOT(on_newConnect_join(qintptr,int )));
        emit this->createTcpConnect(socket,m_tcpProgerssList.count() - 1);
        disconnect(this,SIGNAL(createTcpConnect(qintptr,int)),pro,SLOT(on_newConnect_join(qintptr,int )));


        //连接子线程信号的响应槽函数
        connect(pro,SIGNAL(connected(QString ,int )),this,SLOT(on_progress_connected(QString ,int )));//连接成功
        connect(pro,SIGNAL(disconnected(QString  ,int )),this,SLOT(on_progress_disconnected(QString ,int )));//断开连接
        connect(pro,SIGNAL(newMessage(QByteArray ,int )),this,SLOT(on_progress_newMessage(QByteArray ,int )));//接收到消息
        connect(this,SIGNAL(sendMessage(QByteArray ,int )),pro,SLOT(on_message_send(QByteArray ,int  )));//发送消息
        connect(txt,SIGNAL(textChanged()),this,SLOT(onWidgetTextChanged()));//连接当前界面内容变化时判断保存清理按钮是否可用的槽函数

    }

    else if(ui->combProtocolNet->currentIndex() == 1){//当socket作为客户端连接主机时
        m_isConnectNet = true;//连接成功后就设置对应的成员变量为真
        m_timerNet->start();//作为客服端连接成功时打开计时器
        ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+ui->combHostNet->currentText()+tr(" 端口:")+ui->editPortNet->text()+tr(" 连接服务器成功..."));
        ui->btnListenNet->setText(tr("已打开"));
        ui->btnListenNet->setIcon(QIcon(":/img/getConnect.png"));

        ui->combProtocolNet->setEnabled(false);//设置对应的按钮不可互动
        ui->combHostNet->setEnabled(false);
        ui->editPortNet->setEnabled(false);
        ui->btnUpdateNet->setEnabled(false);
    }
}

void MainWindow::on_socket_disconnected()
{
    if(ui->combProtocolNet->currentIndex() == 0){//当作为tcp服务器断开连接时
        ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+m_tcpSocket->peerAddress().toString()+tr(" 主机名:")+m_tcpSocket->peerName()+tr(" 已断开连接."));
    }

    else if(ui->combProtocolNet->currentIndex() == 1){//当作为tcp客户端断开连接时
        m_isConnectNet = false;
        m_timerNet->stop();
        ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("和服务器断开连接."));
        ui->btnListenNet->setText(tr("已关闭"));
        ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
        ui->combProtocolNet->setEnabled(true);//设置对应的按钮可以互动
        ui->combHostNet->setEnabled(true);
        ui->editPortNet->setEnabled(true);
        ui->btnUpdateNet->setEnabled(true);

        ui->btnSendNet->setEnabled(false);
        if(!(ui->textSendNet->toPlainText().isEmpty() || ui->textSendNet->toPlainText().isNull() || m_isConnectNet == false) && m_tcpSocket->state() == QAbstractSocket::ConnectedState){
            ui->btnSendNet->setEnabled(true);
        }
    }
}


void MainWindow::on_btnSendNet_clicked()
{


    if(ui->combProtocolNet->currentIndex() == 2){//如果不作为tcp服务器和tcp客户端,而做udp通信
        if(ui->textSendNet->toPlainText().isEmpty() == true){//检测发送内容是否为空
            ui->textSendNet->setEnabled(false);
            return;
        }
    }


    //定时器启动关闭,开始重复发送
    if(ui->cheReSendNet->isChecked() == true){//如果选中重复发送
        if(m_timerReSendNet->isActive() == false){//如果定时器停止
            ui->btnSendNet->setText(tr("已打开"));
            ui->btnSendNet->setIcon(QIcon(":/img/getConnect.png"));
            m_timerReSendNet->start();//启动定时器

            if((ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1) && ui->tabWidgetNet->currentIndex() != 0){//
                int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
                for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                    if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                        index = i;
                        break;
                    }
                }

                m_tcpWidgetList.at(index)->append(tr("重复发送开始:"));

            }else{
                ui->textRecNet->append(tr("重复发送开始:"));
            }
        }else if(m_timerReSendNet->isActive() == true){
            ui->btnSendNet->setText(tr("已关闭"));
            ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
            m_timerReSendNet->stop();//关闭定时器


            if((ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1) && ui->tabWidgetNet->currentIndex() != 0){
                int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
                for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                    if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                        index = i;
                        break;
                    }
                }

                m_tcpWidgetList.at(index)->append(tr("重复发送结束."));

            }else{
                ui->textRecNet->append(tr("重复发送结束."));
            }

        }
        return;
    }


    //以下代码当重复发送框没被选中时实现,即发送模式为单次发送
    QString sendStr = ui->textSendNet->toPlainText();
    QString resultStr;

    if(ui->radioSendHexNet->isChecked() == true){//如果勾选发送为16进制
        static QRegularExpression re("\\s");
        sendStr = sendStr.simplified().remove(re);

        if(sendStr.size()%2 != 0){//自动补全
            sendStr.insert(0,'0');
        }

        resultStr = sendStr;//获得hex格式的内容

    }
    else{
        resultStr = sendStr;//获得ascll格式的内容
    }


    //计算索引
    int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
    for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
        if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
            index = i;
            break;
        }
    }

    if(ui->combProtocolNet->currentIndex() == 0 ){//如果当前是tcp服务器
        if(ui->tabWidgetNet->currentIndex() == 0){
            ui->btnSendNet->setEnabled(false);
            return;
        }
        emit sendMessage(resultStr.toUtf8(),index);
    }
    else if(ui->combProtocolNet->currentIndex() == 1){//如果当前是tcp客户端
        if(ui->tabWidgetNet->currentIndex() == 0){
            ui->btnSendNet->setEnabled(false);
            return;
        }

        emit sendMessage(resultStr.toUtf8(),index);
    }
    else if(ui->combProtocolNet->currentIndex() == 2){//如果当前是udp通信
        QString targetIP = ui->editTargetHostNet->text();
        int taregtPort = ui->editTargetPortNet->text().toInt();
        QHostAddress taregtAddr(targetIP);

        if(ui->combUdpCastModeNet->currentIndex() == 0){//udp单播

            m_udpSocket->writeDatagram(resultStr.toUtf8(),taregtAddr,taregtPort);
        }else if(ui->combUdpCastModeNet->currentIndex() == 1){//广播

            m_udpSocket->writeDatagram(resultStr.toUtf8(),taregtAddr,taregtPort);
        }else if(ui->combUdpCastModeNet->currentIndex() == 2){//组播

            m_udpSocket->writeDatagram(resultStr.toUtf8(),taregtAddr,taregtPort);
        }
    }


    m_sendCountNet += resultStr.size();//发送计数
    m_statueLab4.setText(QString::asprintf("%d",m_sendCountNet));

    //以下代码用于UI显示加工内容
    if(ui->cheShowSendNet->isChecked() == true){//如果勾选显示发送框

        if(ui->radioSendAscllNet->isChecked() == true){//以ascll编码形式发送
            resultStr.prepend(tr("[Ascll 发送]:"));
        }else if(ui->radioSendHexNet->isChecked() == true){//以hex编码形式发送
            resultStr.prepend(tr("[Hex 发送]:"));
        }

        if(ui->cheShowTimeNet->isChecked() == true){//如果勾选显示时间
            resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
        }
        if(ui->cheAutoLineNet->isChecked() == true){//如果勾选自动换行
            if(ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1){//作为服务器
                m_tcpWidgetList.at(index)->append(resultStr);
            }
            else if(ui->combProtocolNet->currentIndex() == 2){//udp通信

            ui->textRecNet->append(resultStr);
            }
            return;
        }

        if(ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1){//作为服务器
            m_tcpWidgetList.at(index)->insertPlainText(resultStr);
        }
        else if(ui->combProtocolNet->currentIndex() == 2){//不作为服务器
            ui->textRecNet->insertPlainText(resultStr);
        }

        ui->btnSaveLogNet->setEnabled(true);



    }

}

void MainWindow::on_timerNet_timeout()
{

    if(m_tcpSocket->state() == QAbstractSocket::UnconnectedState){//如果在连接期间检测到连接断开
        m_timerNet->stop();//停止保活计时器

        if(ui->combProtocolNet->currentIndex() == 0){//作为服务器
            ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统]")+tr(" 客户已断开连接."));
        }

        else if(ui->combProtocolNet->currentIndex() == 1 || m_tcpSocket->state() == QAbstractSocket::HostLookupState) {//作为客服端
            ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr(" 服务器异常,已断开连接."));

            m_isConnectNet = false;
            ui->btnListenNet->setText(tr("已关闭"));
            ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
            ui->combProtocolNet->setEnabled(true);//设置对应的按钮可以互动
            ui->combHostNet->setEnabled(true);
            ui->editPortNet->setEnabled(true);
            ui->btnUpdateNet->setEnabled(true);
        }

        else if(ui->combProtocolNet->currentIndex() == 2){//作为udp服务器

        }
    }
}


void MainWindow::on_btnClearSendNet_clicked()
{
    //如果计时器正在运行
    if(m_timerReSendNet->isActive() == true ){
        if(ui->combProtocolNet->currentIndex() == 0 ){

            if(ui->combProtocolNet->currentIndex() == 0 && ui->tabWidgetNet->currentIndex() != 0){
                int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
                for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                    if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                        index = i;
                        break;
                    }
                }

                m_tcpWidgetList.at(index)->append(tr("重复发送结束."));

            }else{
                ui->textRecNet->append(tr("重复发送结束."));
            }

        }
    }

    m_timerReSendNet->stop();//清空发送框会停止计时器
    ui->textSendNet->clear();

    ui->btnSendNet->setEnabled(false);
    if(ui->cheReSendNet->isChecked() == true){
        ui->btnSendNet->setText(tr("已关闭"));
        ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
    }else{
        ui->btnSendNet->setText(tr("发送"));
        ui->btnSendNet->setIcon(QIcon(""));
    }
}


void MainWindow::on_btnClearRecNet_clicked()
{
    if(ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1){//作为tcp主机服务器或tcp客户端
        if(ui->tabWidgetNet->currentIndex() == 0){//即当前为main界面
            ui->textRecNet->clear();
            ui->btnClearRecNet->setEnabled(false);
            m_originalAcceptStringNet = "";//清空原生字符串接收内容

            //清空发送接收计数
            m_recCountNet = 0;
            m_sendCountNet = 0;
            m_statueLab5.setText("0");
            m_statueLab4.setText("0");

        }
        else{//当前为tcp连接对话窗口
            int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
            for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                    index = i;
                    break;
                }
            }

            m_tcpWidgetList.at(index)->clear();
            m_tcpOriRec.removeAt(index);
            QByteArray ba = "";
            m_tcpOriRec.insert(index,ba);
            ui->btnClearRecNet->setEnabled(false);

        }

    }
    else if(ui->combProtocolNet->currentIndex() == 2){//作为udp服务器
        ui->textRecNet->clear();
        ui->btnClearRecNet->setEnabled(false);
        m_originalAcceptStringNet = "";//清空原生字符串接收内容
        //清空发送接收计数
        m_recCountNet = 0;
        m_sendCountNet = 0;
        m_statueLab5.setText("0");
        m_statueLab4.setText("0");
    }

    ui->btnSaveLogNet->setEnabled(false);
    ui->btnSaveDateNet->setEnabled(false);

}


void MainWindow::on_textRecNet_textChanged()
{
    if(ui->textRecNet->toPlainText().isEmpty() == false){
        ui->btnClearRecNet->setEnabled(true);
        ui->btnSaveLogNet->setEnabled(true);
    }else{
        ui->btnClearRecNet->setEnabled(false);
    }

    ui->textRecNet->moveCursor(QTextCursor::End);//接受框内容改变就将滑动条拿到最底部
}


void MainWindow::on_textSendNet_textChanged()
{
    //管理发送框清理按钮是否可用
    if(ui->textSendNet->toPlainText().isEmpty() == true){
        ui->btnClearSendNet->setEnabled(false);
    }else{
        ui->btnClearSendNet->setEnabled(true);
    }


    if(ui->combProtocolNet->currentIndex() == 0 ){//如果当前为tcp服务器
        //只有当发送框有文本并且当前端口和socket已连接时才能与发送按钮互动
        if(!(ui->textSendNet->toPlainText().isEmpty() || ui->textSendNet->toPlainText().isNull())){
            ui->btnSendNet->setEnabled(true);
            if(ui->tabWidgetNet->currentIndex() == 0){//如果当前为main界面,且作为tcp服务器时
                ui->btnSendNet->setEnabled(false);

            }
        }else{

            ui->btnSendNet->setEnabled(false);
            if(ui->cheReSendNet->isChecked() == true){//如果勾选重复发送
                if(m_timerReSendNet->isActive() == true){//如果此时正在启动重复发送
                    ui->textRecNet->append(tr("重复发送停止."));
                }
                ui->btnSendNet->setText(tr("已关闭"));
                ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
            }else if(ui->cheReSendNet->isChecked() == false){//如果没有勾选重复发送
                ui->btnSendNet->setText(tr("发送"));
                ui->btnSendNet->setIcon(QIcon(""));
            }

            m_timerReSendNet->stop();

        }
    }

    else if(ui->combProtocolNet->currentIndex() == 1){//如果作为tcp客户端
        //只有当发送框有文本并且当前端口和socket已连接时才能与发送按钮互动
        if(!ui->textSendNet->toPlainText().isEmpty() && ui->tabWidgetNet->currentIndex() != 0){
            ui->btnSendNet->setEnabled(true);
        }else{

            ui->btnSendNet->setEnabled(false);
            if(ui->cheReSendNet->isChecked() == true){//如果勾选重复发送
                if(m_timerReSendNet->isActive() == true){//如果此时正在启动重复发送
                    ui->textRecNet->append(tr("重复发送停止."));
                }
                ui->btnSendNet->setText(tr("已关闭"));
                ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
            }else if(ui->cheReSendNet->isChecked() == false){//如果没有勾选重复发送
                ui->btnSendNet->setText(tr("发送"));
                ui->btnSendNet->setIcon(QIcon(""));
            }

            m_timerReSendNet->stop();

        }
    }
    else if(ui->combProtocolNet->currentIndex() == 2){//如果当前为udp通信
        if(ui->combUdpCastModeNet->currentIndex() == 0 || ui->combUdpCastModeNet->currentIndex() == 1){//如果当前为udp单播或者广播
            if(!(ui->textSendNet->toPlainText().isEmpty() || m_isBindNet == false) ){
                ui->btnSendNet->setEnabled(true);
            }else{
                ui->btnSendNet->setEnabled(false);
                if(ui->cheReSendNet->isChecked() == true){//如果勾选重复发送
                    if(m_timerReSendNet->isActive() == true){//如果此时正在启动重复发送
                        ui->textRecNet->append(tr("重复发送停止."));
                    }
                    ui->btnSendNet->setText(tr("已关闭"));
                    ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
                }else if(ui->cheReSendNet->isChecked() == false){//如果没有勾选重复发送
                    ui->btnSendNet->setText(tr("发送"));
                    ui->btnSendNet->setIcon(QIcon(""));
                }

                m_timerReSendNet->stop();
            }
        }

        else if(ui->combUdpCastModeNet->currentIndex() == 2){//如果当前为udp组播
            if(m_isJoinMultiNet == true && !ui->textSendNet->toPlainText().isEmpty()){
                ui->btnSendNet->setEnabled(true);
            }else {
                ui->btnSendNet->setEnabled(false);
                if(ui->cheReSendNet->isChecked() == true){//如果勾选重复发送
                    if(m_timerReSendNet->isActive() == true){//如果此时正在启动重复发送
                        ui->textRecNet->append(tr("重复发送停止."));
                    }
                    ui->btnSendNet->setText(tr("已关闭"));
                    ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
                }else if(ui->cheReSendNet->isChecked() == false){//如果没有勾选重复发送
                    ui->btnSendNet->setText(tr("发送"));
                    ui->btnSendNet->setIcon(QIcon(""));
                }

                m_timerReSendNet->stop();
            }
        }

    }

}

void MainWindow::on_tcpSocket_readyRead()
{
    //以下代码为正常接收
    QByteArray byte = m_tcpSocket->readAll();//先获取接收内容,再加工

    QString resultStr = byte;

    if(ui->radioRecAscllNet->isChecked() == true){
        resultStr = byte;
    }
    else if(ui->radioRecHexNet->isChecked() == true){//如果勾选接收为16进制

        static QRegularExpression re("\\s");
        resultStr = resultStr.simplified().remove(re);

        if(resultStr.size()%2 != 0){//自动补全
            resultStr.insert(0,'0');
        }

        QString hexStr;
        bool ok;
        for(int i = 0;i < resultStr.size()/2 ; ++i){
            hexStr += resultStr.mid(2*i,2).toInt(&ok,16);//切割字符串
        }

        resultStr = hexStr;//获得hex格式的内容


    }

    //以下代码用于二次加工
    ui->btnSaveLogNet->setEnabled(true);
    ui->btnSaveDateNet->setEnabled(true);

    m_originalAcceptStringNet += resultStr;//写入原生字符串

    m_recCountNet += resultStr.size();//接收计数
    m_statueLab5.setText(QString::asprintf("%d",m_recCountNet));//状态栏显示


    if(ui->radioRecAscllNet->isChecked() == true){//以ascll编码形式接收
        resultStr.prepend(tr("[Ascll 接收]:"));
    }else if(ui->radioRecHexNet->isChecked() == true){//以hex编码形式接收
        resultStr.prepend(tr("[Hex 接收]:"));
    }

    if(ui->cheShowTimeNet->isChecked() == true){//如果勾选显示时间
        resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
    }
    if(ui->cheAutoLineNet->isChecked() == true){//如果勾选自动换行
        ui->textRecNet->append(resultStr);
        return;
    }

    ui->textRecNet->insertPlainText(resultStr);

}


void MainWindow::on_btnSaveLogNet_clicked()
{
    QString savePath = QFileDialog::getSaveFileName(0,tr("请选择保存位置"),QDir::homePath(),"txt(*.txt);;all(*.*)");
    QFile file(savePath);

    if(file.open(QIODevice::WriteOnly) == false){//如果文件打开失败
        QMessageBox::warning(0,tr("警告"),tr("日志保存失败!"));
        return;
    }
    QTextStream aStream(&file);

    //以下代码实现保存功能
    if(ui->combProtocolNet->currentIndex() == 0){//作为tcp服务器

        if(ui->tabWidgetNet->currentIndex() == 0){//即当前界面为main界面
            aStream << ui->textRecNet->toPlainText();
        }
        else{
            int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
            for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                    index = i;
                    break;
                }
            }
            aStream << m_tcpWidgetList.at(index)->toPlainText();
        }

    }
    else{//不作为服务器
        aStream << ui->textRecNet->toPlainText();
    }

    file.close();
}


void MainWindow::on_cheReSendNet_stateChanged(int arg1)
{
    if(arg1 == Qt::Unchecked){//关闭重复发送
        if(m_timerReSendNet->isActive() == true){//如果取消勾选重复发送时正在重复发送

            if(ui->combProtocolNet->currentIndex() == 0 && ui->tabWidgetNet->currentIndex() != 0){
                int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
                for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                    if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                        index = i;
                        break;
                    }
                }

                m_tcpWidgetList.at(index)->append(tr("重复发送结束."));

            }else{
                ui->textRecNet->append(tr("重复发送结束."));
            }

        }
        m_timerReSendNet->stop();
        ui->btnSendNet->setText(tr("发送"));
        ui->btnSendNet->setIcon(QIcon(""));

    }else if(arg1 == Qt::Checked){//打开重复发送
        m_timerReSendNet->stop();
        ui->btnSendNet->setText(tr("已关闭"));
        ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));

    }
}


void MainWindow::on_spinBoxSendIntervalNet_valueChanged(int arg1)
{
    m_timerReSendNetInterval = arg1;//更新定时器触发间隔
    m_timerReSendNet->setInterval(m_timerReSendNetInterval);
}

void MainWindow::on_timerReSend_timeout()
{

    QString sendStr = ui->textSendNet->toPlainText();
    QString resultStr;

    if(ui->radioSendHexNet->isChecked() == true){//如果勾选发送为16进制
        static QRegularExpression re("\\s");
        sendStr = sendStr.simplified().remove(re);

        if(sendStr.size()%2 != 0){//自动补全
            sendStr.insert(0,'0');
        }

        resultStr = sendStr;//获得hex格式的内容

    }
    else{
        resultStr = sendStr;//获得ascll格式的内容
    }


    //计算索引
    int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
    for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
        if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
            index = i;
            break;
        }
    }

    if(ui->combProtocolNet->currentIndex() == 0 ){//如果当前是tcp服务器
        if(ui->tabWidgetNet->currentIndex() == 0){
            ui->btnSendNet->setEnabled(false);
            return;
        }
        emit sendMessage(resultStr.toUtf8(),index);
    }
    else if(ui->combProtocolNet->currentIndex() == 1){//如果当前是tcp客户端
        if(ui->tabWidgetNet->currentIndex() == 0){
            ui->btnSendNet->setEnabled(false);
            return;
        }

        emit sendMessage(resultStr.toUtf8(),index);
    }
    else if(ui->combProtocolNet->currentIndex() == 2){//如果当前是udp通信
        QString targetIP = ui->editTargetHostNet->text();
        int taregtPort = ui->editTargetPortNet->text().toInt();
        QHostAddress taregtAddr(targetIP);

        if(ui->combUdpCastModeNet->currentIndex() == 0){//udp单播

            m_udpSocket->writeDatagram(resultStr.toUtf8(),taregtAddr,taregtPort);
        }else if(ui->combUdpCastModeNet->currentIndex() == 1){//广播

            m_udpSocket->writeDatagram(resultStr.toUtf8(),taregtAddr,taregtPort);
        }else if(ui->combUdpCastModeNet->currentIndex() == 2){//组播

            m_udpSocket->writeDatagram(resultStr.toUtf8(),taregtAddr,taregtPort);
        }
    }


    m_sendCountNet += resultStr.size();//发送计数
    m_statueLab4.setText(QString::asprintf("%d",m_sendCountNet));

    //以下代码用于UI显示加工内容
    if(ui->cheShowSendNet->isChecked() == true){//如果勾选显示发送框

        if(ui->radioSendAscllNet->isChecked() == true){//以ascll编码形式发送
            resultStr.prepend(tr("[Ascll 发送]:"));
        }else if(ui->radioSendHexNet->isChecked() == true){//以hex编码形式发送
            resultStr.prepend(tr("[Hex 发送]:"));
        }

        if(ui->cheShowTimeNet->isChecked() == true){//如果勾选显示时间
            resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
        }
        if(ui->cheAutoLineNet->isChecked() == true){//如果勾选自动换行
            if(ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1){//作为服务器
                m_tcpWidgetList.at(index)->append(resultStr);
            }
            else if(ui->combProtocolNet->currentIndex() == 2){//udp通信

            ui->textRecNet->append(resultStr);
            }
            return;
        }

        if(ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1){//作为服务器
            m_tcpWidgetList.at(index)->insertPlainText(resultStr);
        }
        else if(ui->combProtocolNet->currentIndex() == 2){//不作为服务器
            ui->textRecNet->insertPlainText(resultStr);
        }

        ui->btnSaveLogNet->setEnabled(true);



    }
}


void MainWindow::on_btnRecNet_clicked()
{
    if(ui->combProtocolNet->currentIndex() == 0 || ui->combProtocolNet->currentIndex() == 1){//如果当为tcp客户端协议或tcp服务器协议

        if(m_isConnectNet == true && m_isAcceptRecNet == true ){
            ui->btnRecNet->setText("拒收");
            ui->btnRecNet->setIcon(QIcon(":/img/loseConnect.png"));
            m_isAcceptRecNet = false;//修改为拒收状态
//            disconnect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(on_tcpSocket_readyRead()));//断开接受信息槽函数
        }else if(m_isConnectNet == true && m_isAcceptRecNet == false){
//            m_tcpSocket->readAll();//将接收缓冲区清空

            ui->btnRecNet->setText("接收");
            ui->btnRecNet->setIcon(QIcon(":/img/getConnect.png"));
            m_isAcceptRecNet = true;//修改为接收状态
//            connect(m_tcpSocket,SIGNAL(readyRead()),this,SLOT(on_tcpSocket_readyRead()));//连接接受信息槽函数
        }

    }else if(ui->combProtocolNet->currentIndex() == 2){//如果当前为udp协议
        if(ui->combUdpCastModeNet->currentIndex() == 0 || ui->combUdpCastModeNet->currentIndex() == 1){//如果当前为单播或广播
            if(m_isBindNet == true && m_isAcceptRecNet == true ){
                ui->btnRecNet->setText("拒收");
                ui->btnRecNet->setIcon(QIcon(":/img/loseConnect.png"));
                m_isAcceptRecNet = false;//修改为拒收状态
                disconnect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(on_udpSocket_readyRead()));//断开接受信息槽函数
            }else if(m_isBindNet == true && m_isAcceptRecNet == false){

                ui->btnRecNet->setText("接收");
                ui->btnRecNet->setIcon(QIcon(":/img/getConnect.png"));
                m_isAcceptRecNet = true;//修改为接收状态

                m_udpSocket->abort();//关闭当前udp套接字连接
                QHostAddress addr(ui->combHostNet->currentText());
                int port = ui->editPortNet->text().toInt();
                m_udpSocket->bind(addr,port);

                connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(on_udpSocket_readyRead()));//连接接受信息槽函数
            }
        }
        else if(ui->combUdpCastModeNet->currentIndex() == 2){//如果当前为组播

        }

    }

}


void MainWindow::on_radioSendAscllNet_clicked(bool checked)
{
    if(checked == true){
        m_statueLab3.setText(tr("发送设置:Ascll"));

        //发送框内容进制转换
        QString temp = ui->textSendNet->toPlainText();
        ui->textSendNet->clear();

        static QRegularExpression re("\\s");
        temp = temp.simplified().remove(re);

        if(temp.size()%2 != 0){//自动补全
            temp.insert(0,'0');
        }

        QString resultStr;

        bool ok;
        for(int i = 0;i < temp.size()/2;++i){
            resultStr += temp.mid(2*i,2).toInt(&ok,16);//切割字符串
        }

        ui->textSendNet->appendPlainText(resultStr);
    }else{
        m_statueLab3.setText(tr("发送设置:Hex"));
    }
}


void MainWindow::on_radioSendHexNet_clicked(bool checked)
{
    if(checked == true){
        m_statueLab3.setText(tr("发送设置:Hex"));


        //发送框内容进制转换
        QByteArray temp = ui->textSendNet->toPlainText().toUtf8();
        ui->textSendNet->clear();
        QString resultStr;

        resultStr = QString::fromUtf8(temp.toHex());
        for(int i = resultStr.size() - 2;i > 0; --i){//插入空格分隔符
            if(i % 2 == 0){
                resultStr.insert(i," ");
            }
        }
        ui->textSendNet->appendPlainText(resultStr);

    }else{
        m_statueLab3.setText(tr("发送设置:Ascll"));
    }
}


void MainWindow::on_btnSaveDateNet_clicked()
{
    QString savePath = QFileDialog::getSaveFileName(0,tr("请选择保存位置"),QDir::homePath(),"all(*.*);;txt(*.txt);;hex(*.hex);;dat(*.dat);;ini(*.ini)");
    QFile file(savePath);

    if(file.open(QIODevice::WriteOnly) == false){//如果文件打开失败
        QMessageBox::warning(0,tr("警告"),tr("文件保存失败!"));
        return;
    }

    //以下代码实现保存功能

    if(ui->combProtocolNet->currentIndex() == 0){//作为tcp主机服务器


        if(ui->tabWidgetNet->currentIndex() == 0){//即当前为main界面
            file.write(m_originalAcceptStringNet.toUtf8());
        }
        else{//当前为tcp连接对话窗口
            int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
            for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
                if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                    index = i;
                    break;
                }
            }
            file.write(m_tcpOriRec.at(index));
        }

    }
    else {//不做为tcp服务器
        file.write(m_originalAcceptStringNet.toUtf8());
    }

    file.close();
}


void MainWindow::on_combUdpCastModeNet_currentIndexChanged(int index)
{
    if(index == 0){//udp单播
        ui->editTargetHostNet->setText(getIPv4Address().at(0).toString());//设置默认为本机地址);
        ui->editTargetPortNet->setText("3001");
        ui->btnJoinBroadMulticastNet->setEnabled(false);
        ui->btnListenNet->setEnabled(true);//设置连接按钮可以互动
    }else if(index == 1){//udp广播
        ui->editTargetHostNet->setText("255.255.255.255");//设置默认广播地址
        ui->editTargetPortNet->setText("3001");
        ui->btnJoinBroadMulticastNet->setEnabled(false);
        ui->btnListenNet->setEnabled(true);//设置连接按钮可以互动
    }else if(index == 2){//udp组播

        ui->editTargetHostNet->setText("239.255.255.0");//设置默认为本机地址);
        ui->editTargetPortNet->setText("3001");

        if(!ui->editTargetPortNet->text().isEmpty() && !ui->editTargetHostNet->text().isEmpty()){
            ui->btnJoinBroadMulticastNet->setEnabled(true);
        }

        ui->btnListenNet->setEnabled(false);//设置连接按钮不可互动
    }
}

void MainWindow::on_udpSocket_readyRead()
{
    //
    while(m_udpSocket->hasPendingDatagrams()){//检测是否有数据须要读取

        //以下代码为正常接收,先获取接收内容,再加工
        QByteArray datagram;
        datagram.resize(m_udpSocket->pendingDatagramSize());
        m_udpSocket->readDatagram(datagram.data(),datagram.size());
        QString resultStr = datagram.data();

        if(ui->radioRecAscllNet->isChecked() == true){
            resultStr = datagram;
        }
        else if(ui->radioRecHexNet->isChecked() == true){//如果勾选接收为16进制

            static QRegularExpression re("\\s");
            resultStr = resultStr.simplified().remove(re);

            if(resultStr.size()%2 != 0){//自动补全
                resultStr.insert(0,'0');
            }

            QString hexStr;
            bool ok;
            for(int i = 0;i < resultStr.size()/2 ; ++i){
                hexStr += resultStr.mid(2*i,2).toInt(&ok,16);//切割字符串
            }

            resultStr = hexStr;//获得hex格式的内容


        }

        //以下代码用于二次加工
        ui->btnSaveLogNet->setEnabled(true);
        ui->btnSaveDateNet->setEnabled(true);

        m_originalAcceptStringNet += resultStr;//写入原生字符串

        m_recCountNet += resultStr.size();//发送计数
        m_statueLab5.setText(QString::asprintf("%d",m_recCountNet));//状态栏显示


        if(ui->radioRecAscllNet->isChecked() == true){//以ascll编码形式接收
            resultStr.prepend(tr("[Ascll 接收]:"));
        }else if(ui->radioRecHexNet->isChecked() == true){//以hex编码形式接收
            resultStr.prepend(tr("[Hex 接收]:"));
        }

        if(ui->cheShowTimeNet->isChecked() == true){//如果勾选显示时间
            resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
        }
        if(ui->cheAutoLineNet->isChecked() == true){//如果勾选自动换行
            ui->textRecNet->append(resultStr);
            return;
        }

        ui->textRecNet->insertPlainText(resultStr);


    }

}


void MainWindow::on_btnJoinBroadMulticastNet_clicked()
{
    if(m_isJoinMultiNet == false){//如果当前状态为没加入组播
        QString IP = ui->editTargetHostNet->text();//获取多播组地址
        int port = ui->editTargetPortNet->text().toInt();//获取多播组端口
        QHostAddress addr(IP);
        if(m_udpSocket->bind(QHostAddress::AnyIPv4,port,QUdpSocket::ShareAddress)){//绑定多播地址
            if(m_udpSocket->joinMulticastGroup(addr) == false){//如果加入多播组失败
                QMessageBox::warning(0,tr("警告"),tr("加入组播失败."));
                m_udpSocket->abort();
                return;
            }

            //以下代码当加入组播成功时执行
            m_isJoinMultiNet = true;
            ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("加入组播成功..."));

            //检测发送按钮是否可以互动
            if(!ui->textSendNet->toPlainText().isEmpty()){
                ui->btnSendNet->setEnabled(true);
            }

            //设置部分ui控件不可互动
            ui->combProtocolNet->setEnabled(false);
            ui->combHostNet->setEnabled(false);
            ui->editPortNet->setEnabled(false);
            ui->btnUpdateNet->setEnabled(false);
            ui->combUdpCastModeNet->setEnabled(false);
            ui->editTargetHostNet->setEnabled(false);
            ui->editTargetPortNet->setEnabled(false);

            //设置本按钮文字图标
            ui->btnJoinBroadMulticastNet->setText(tr("已加入组播"));
            ui->btnJoinBroadMulticastNet->setIcon(QIcon(":/img/getConnect.png"));

        }
        else{
            QMessageBox::warning(0,tr("警告"),tr("绑定多播端口地址失败"));
            return;
        }
    }
    else if(m_isJoinMultiNet == true){//如果已经加入组播
        m_isJoinMultiNet = false;
        ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("已离开组播"));
        m_udpSocket->leaveMulticastGroup(QHostAddress(ui->editTargetHostNet->text()));//离开组播
        m_udpSocket->abort();//解除组播绑定

        if(m_timerReSendNet->isActive() == true){//如果当前正在重复发送
            ui->textRecNet->append(tr("重复发送结束."));
            m_timerReSendNet->stop();
            ui->btnSendNet->setText(tr("已关闭"));
            ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
        }
        ui->btnSendNet->setEnabled(false);//发送按钮不可互动

        //设置部分ui控件可以互动
        ui->combProtocolNet->setEnabled(true);
        ui->combHostNet->setEnabled(true);
        ui->editPortNet->setEnabled(true);
        ui->btnUpdateNet->setEnabled(true);
        ui->combUdpCastModeNet->setEnabled(true);
        ui->editTargetHostNet->setEnabled(true);
        ui->editTargetPortNet->setEnabled(true);

        //设置本按钮文字图标
        ui->btnJoinBroadMulticastNet->setText(tr("未加入组播"));
        ui->btnJoinBroadMulticastNet->setIcon(QIcon(":/img/loseConnect.png"));
    }


}



void MainWindow::on_asTcpClient_Connecte()
{
    if(ui->combProtocolNet->currentIndex() == 1){//当socket作为客户端连接主机时
        m_tcpSocket->readAll();//将原有的接收缓冲读取掉不使用
        m_isConnectNet = true;//连接成功后就设置对应的成员变量为真
        m_timerNet->start();//作为客服端连接成功时打开计时器
        ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+ui->combHostNet->currentText()+tr(" 端口:")+ui->editPortNet->text()+tr(" 连接服务器成功..."));
        ui->btnListenNet->setText(tr("已打开"));
        ui->btnListenNet->setIcon(QIcon(":/img/getConnect.png"));

        ui->combProtocolNet->setEnabled(false);//设置对应的按钮不可互动
        ui->combHostNet->setEnabled(false);
        ui->editPortNet->setEnabled(false);
        ui->btnUpdateNet->setEnabled(false);
    }
}

void MainWindow::on_progress_connected(QString address, int index)
{
    ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+address+tr(" 已连接 ..."));
    ui->tabWidgetNet->addTab(m_tcpWidgetList.at(index),m_tcpProgerssList.at(index)->m_peerAddress);//添加tablewidget对话框 tr("窗口")+QString::asprintf("%d",index))
    ui->tabWidgetNet->setCurrentWidget(m_tcpWidgetList.at(index));
    m_tcpWidgetList.at(index)->append(m_tcpProgerssList.at(index)->m_peerAddress+tr("已连接..."));

    if(ui->combProtocolNet->currentIndex() == 1){//如果当前为tcp客户端
        m_isConnectNet = true;//连接成功后就设置对应的成员变量为真
        ui->btnListenNet->setText(tr("已打开"));
        ui->btnListenNet->setIcon(QIcon(":/img/getConnect.png"));
        ui->combProtocolNet->setEnabled(false);//设置对应的按钮不可互动

        ui->btnListenNet->setEnabled(true);

        //判断发送按钮是否可以互动
        ui->btnSendNet->setEnabled(false);
        if(!ui->textSendNet->toPlainText().isEmpty() && ui->tabWidgetNet->currentIndex() != 0){
            ui->btnSendNet->setEnabled(true);

        }
    }

}

void MainWindow::on_progress_disconnected(QString peerAddress, int index)
{
    ui->textRecNet->append(QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("地址:")+peerAddress+tr(" 已断开连接"));

    if(m_timerReSendNet->isActive() == true){//如果断开连接时,定时器正在运行并且断开连接的窗口是当前对话的窗口则关闭重复发送
        //计算索引
        int index2 = -1;//index是根据ui当前tcp对话窗口计算得到的索引
        for(int i =0;i <m_tcpWidgetList.count();++i){
            if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                index2 = i;
                break;
            }
        }
        if(index == index2){//检查是否为当前窗口断开连接
            m_timerReSendNet->stop();

            ui->btnSendNet->setText(tr("已关闭"));
            ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
        }

    }



    //释放线程和程序占用的资源
    m_tcpThreadList.at(index)->quit();
    m_tcpThreadList.at(index)->wait();
    delete m_tcpProgerssList.at(index);
//    emit goDeleteProgress(index);
//////////
    m_tcpProgerssList.removeAt(index);
    mytcpprogress*  p;
    p = NULL;
    m_tcpProgerssList.insert(index,p);
//////////

    m_tcpThreadList.at(index)->deleteLater();

    m_tcpWidgetList.at(index)->deleteLater();
    ///////
    m_tcpWidgetList.removeAt(index);
    QTextBrowser* b;
    b = NULL;
    m_tcpWidgetList.insert(index,b);
    ///////


    //如果当前为tcp客户端,设置连接按钮为关闭状态
    if(ui->combProtocolNet->currentIndex() == 1){
        ui->btnListenNet->setText(tr("已关闭"));
        ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
        ui->btnListenNet->setEnabled(false);

        //判断界面列表是否全为空,进而判断当前是否还有连接存在
        bool widgetAllIsNull = false;
        for(int i = 0; i < m_tcpWidgetList.count() ; ++i){
            if(m_tcpWidgetList.at(i) != NULL){
                widgetAllIsNull = false;
                break;
            }
            widgetAllIsNull = true;
        }


        if(widgetAllIsNull == true){//如果当前界面只有main,没有其他窗口
            ui->combProtocolNet->setEnabled(true);//设置对应的按钮可互动

            //释放进程资源,和线程资源
            for(int i = m_tcpProgerssList.count() - 1;i >= 0 ;--i){
                if(m_tcpProgerssList.at(i) != NULL){
                    m_tcpThreadList.at(i)->quit();
                    m_tcpThreadList.at(i)->wait();
                    delete m_tcpProgerssList.at(i);
    //                emit deleteProgress(i);
                    m_tcpThreadList.at(i)->deleteLater();

                }
            }

    //        释放窗口资源
            for(int i = m_tcpWidgetList.count() - 1;i >= 0 ;--i){
                if(m_tcpWidgetList.at(i) != NULL){
                    m_tcpWidgetList.at(i)->deleteLater();

                }
            }

            //重置资源列表
            m_tcpProgerssList.clear();
            m_tcpThreadList.clear();
            m_tcpWidgetList.clear();
            m_tcpOriRec.clear();
        }
    }

}

void MainWindow::on_progress_newMessage(QByteArray recData, int index)
{
    //以下代码为正常接收
    QByteArray byte = recData;//先获取接收内容,再加工

    QString resultStr = byte;

    if(ui->radioRecAscllNet->isChecked() == true){
        resultStr = byte;
    }
    else if(ui->radioRecHexNet->isChecked() == true){//如果勾选接收为16进制

        static QRegularExpression re("\\s");
        resultStr = resultStr.simplified().remove(re);

        if(resultStr.size()%2 != 0){//自动补全
            resultStr.insert(0,'0');
        }

        QString hexStr;
        bool ok;
        for(int i = 0;i < resultStr.size()/2 ; ++i){
            hexStr += resultStr.mid(2*i,2).toInt(&ok,16);//切割字符串
        }

        resultStr = hexStr;//获得hex格式的内容

    }




    //如果当前为接收状态
    if(m_isAcceptRecNet == true){
        QByteArray a = m_tcpOriRec.at(index);
        a += resultStr;
        m_tcpOriRec.removeAt(index);
        m_tcpOriRec.insert(index,a);

        //以下代码用于二次加工
        ui->btnSaveLogNet->setEnabled(true);
        if(ui->tabWidgetNet->currentWidget() == m_tcpWidgetList.at(index)){
            ui->btnSaveDateNet->setEnabled(true);
        }

        m_recCountNet += resultStr.size();//发送计数
        m_statueLab5.setText(QString::asprintf("%d",m_recCountNet));//状态栏显示


        if(ui->radioRecAscllNet->isChecked() == true){//以ascll编码形式接收
            resultStr.prepend(tr("[Ascll 接收]:"));
        }else if(ui->radioRecHexNet->isChecked() == true){//以hex编码形式接收
            resultStr.prepend(tr("[Hex 接收]:"));
        }

        if(ui->cheShowTimeNet->isChecked() == true){//如果勾选显示时间
            resultStr.prepend(QTime::currentTime().toString("hh:mm:ss"));
        }
        if(ui->cheAutoLineNet->isChecked() == true){//如果勾选自动换行

            m_tcpWidgetList.at(index)->append(resultStr);

            return;
        }

        m_tcpWidgetList.at(index)->insertPlainText(resultStr);

    }




}


void MainWindow::on_tabWidgetNet_currentChanged(int index)
{
    if(m_timerReSendNet->isActive() == true){//如果切换聊天界面时正在重复发送则停止重复发送
        ui->btnSendNet->setText(tr("已关闭"));
        ui->btnSendNet->setIcon(QIcon(":/img/loseConnect.png"));
        m_timerReSendNet->stop();//关闭定时器
        ui->textRecNet->append( QTime::currentTime().toString("hh:mm:ss")+tr(" [系统] ")+tr("重复发送时请勿切换窗口,当前已结束重复发送."));

    }

    ui->btnSendNet->setEnabled(false);
    if(index != 0 && !ui->textSendNet->toPlainText().isEmpty()){
        ui->btnSendNet->setEnabled(true);
    }

    //切换页面时判断保存日志按钮,保存数据按钮,清理按钮是否可用
    ui->btnSaveDateNet->setEnabled(false);
    ui->btnSaveLogNet->setEnabled(false);
    ui->btnClearRecNet->setEnabled(false);



    //计算索引
    int index2 = -1;//index是根据ui当前tcp对话窗口计算得到的索引
    for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
        if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
            index2 = i;
            break;
        }
    }

    if(index == 0){//当前为main界面
        if(!ui->textRecNet->toPlainText().isEmpty()){

            ui->btnSaveLogNet->setEnabled(true);
            ui->btnClearRecNet->setEnabled(true);
        }

        if(ui->combProtocolNet->currentIndex() == 1){//如果为tcp客户端
            ui->btnListenNet->setText(tr("已关闭"));
            ui->btnListenNet->setIcon(QIcon(":/img/loseConnect.png"));
            ui->btnListenNet->setEnabled(false);
        }
    }
    else{//不为main界面

        if(m_tcpWidgetList.at(index2)->toPlainText().isEmpty()){//如果当前界面内容为空

            ui->btnSaveLogNet->setEnabled(false);
            ui->btnClearRecNet->setEnabled(false);
        }
        else{//如果当前界面内容不为空

            ui->btnSaveLogNet->setEnabled(true);
            ui->btnClearRecNet->setEnabled(true);
        }

        //判断保存数据按钮是否可用

        if(index2 != -1 && !m_tcpOriRec.at(index2).isEmpty()){
            ui->btnSaveDateNet->setEnabled(true);
        }else{
            ui->btnSaveDateNet->setEnabled(false);
        }

        //判断断开按钮是否可以互动
        if(ui->combProtocolNet->currentIndex() == 1){//如果为tcp客户端
            ui->btnListenNet->setText(tr("已连接"));
            ui->btnListenNet->setIcon(QIcon(":/img/getConnect.png"));
            ui->btnListenNet->setEnabled(true);
        }

    }

}

void MainWindow::onWidgetTextChanged()
{
    QTextBrowser* T = (QTextBrowser*)sender();
    if(T == ui->tabWidgetNet->currentWidget()){//如果信号发送者时当前界面的textbrower
        if(T->toPlainText().isEmpty()){//如果当前界面内容为空

            ui->btnSaveLogNet->setEnabled(false);
            ui->btnClearRecNet->setEnabled(false);
        }
        else{//如果当前界面内容不为空

            ui->btnSaveLogNet->setEnabled(true);
            ui->btnClearRecNet->setEnabled(true);
        }

        //判断保存数据按钮是否可用
        //计算索引
        int index = -1;//index是根据ui当前tcp对话窗口计算得到的索引
        for(int i =m_tcpWidgetList.count() - 1;i >= 0;--i){
            if(m_tcpWidgetList.at(i) == ui->tabWidgetNet->currentWidget()){
                index = i;
                break;
            }
        }
        if(index != -1 && !m_tcpOriRec.at(index).isEmpty()){
            ui->btnSaveDateNet->setEnabled(true);
        }else{
            ui->btnSaveDateNet->setEnabled(false);
        }
    }
}

void MainWindow::closeEvent(QCloseEvent *e)
{

    //释放进程资源,和线程资源
    for(int i = m_tcpProgerssList.count() - 1;i >= 0 ;--i){
        if(m_tcpProgerssList.at(i) != NULL){
            m_tcpThreadList.at(i)->quit();
            m_tcpThreadList.at(i)->wait();
            delete m_tcpProgerssList.at(i);
//            emit goDeleteProgress(i);
            m_tcpThreadList.at(i)->deleteLater();

        }
    }



    //释放窗口资源
    for(int i = m_tcpWidgetList.count() - 1;i >= 0 ;--i){
        if(m_tcpWidgetList.at(i) != NULL){
            m_tcpWidgetList.at(i)->deleteLater();

        }
    }

    m_tcpOriRec.clear();

    e->accept();
}



void MainWindow::on_btnNewTcpServiceNet_clicked()
{
    QString IP = ui->combHostNet->currentText();
    int port = ui->editPortNet->text().toInt();


    QRegExp re("^(?:(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])$");
    if(!re.exactMatch(IP) || ui->editPortNet->text().isEmpty() || ui->editPortNet->text().toInt() < 0 || ui->editPortNet->text().toInt() > 65535){//检测地址端口是否符合规范
        QMessageBox::warning(0,tr("警告"),tr("服务器配置出错"));
        return;
    }

    //判断是否要添加重复的服务器地址
    for(int i = 0;i < m_tcpProgerssList.count();++i){
        if(m_tcpProgerssList.at(i) != NULL){
            if(m_tcpProgerssList.at(i)->m_peerAddress == ui->combHostNet->currentText().simplified()){
                int result = -1;
                result = QMessageBox::warning(0,tr("警告"),tr("重复连接同一个地址的同一个端口可能会导致程序出错,是否继续?"),QMessageBox::Ok | QMessageBox::Cancel);
                if(result == QMessageBox::Ok){
                    break;
                }else{
                    return;
                }
            }
        }

    }


    mytcpprogress* pro = new mytcpprogress;
    QThread* thr = new QThread;
    pro->moveToThread(thr);//移动程序到线程
    thr->start();//启动线程
    QTextBrowser* txt = new QTextBrowser;
    m_tcpProgerssList.append(pro);
    m_tcpThreadList.append(thr);
    m_tcpWidgetList.append(txt);
    m_tcpOriRec.append("");

    txt->setFont(this->font());//新窗口字体和主窗口一致
    connect(txt,SIGNAL(textChanged()),txt,SLOT([=](){txt->moveCursor(QTextCursor::End)}));//当有新内容时自动移动到最新的地方

    connect(this,SIGNAL(newTcpServiceProgress(QString,int,int)),pro,SLOT(onNewTcpServiceProgress(QString,int,int)));//连接主线程发动tcp客户端连接请求
    emit newTcpServiceProgress(IP,port,m_tcpProgerssList.count() - 1);
    disconnect(this,SIGNAL(newTcpServiceProgress(QString,int,int)),pro,SLOT(onNewTcpServiceProgress(QString,int,int)));//断开主线程发动tcp客户端连接请求


    connect(pro,SIGNAL(connected(QString,int)),this,SLOT(on_progress_connected(QString ,int )));//当子线程发送连接成功信号时做出响应
    connect(pro,SIGNAL(disconnected(QString,int)),this,SLOT(on_progress_disconnected(QString ,int )));
    connect(pro,SIGNAL(newMessage(QByteArray,int)),this,SLOT(on_progress_newMessage(QByteArray ,int )));
    connect(this,SIGNAL(sendMessage(QByteArray ,int )),pro,SLOT(on_message_send(QByteArray ,int  )));//发送消息
    connect(txt,SIGNAL(textChanged()),this,SLOT(onWidgetTextChanged()));//连接当前界面内容变化时判断保存清理按钮是否可用的槽函数

}



